ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2025-05-10 03:10:39
Exec Total Coverage
Lines: 99 7678 1.3%
Functions: 1 200 0.5%
Branches: 14 6779 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "new_subscr.h"
15 #include "subscr.h"
16 #include "zq/zq_tiles.h"
17 #include "zq/zquest.h"
18 #include "tiles.h"
19 #include "zq/zq_misc.h"
20 #include "zq/zq_class.h"
21 #include "base/zsys.h"
22 #include "base/colors.h"
23 #include "base/qst.h"
24 #include "gui/jwin.h"
25 #include <base/new_menu.h>
26 #include "base/jwinfsel.h"
27 #include "hero_tiles.h"
28 #include "zq/questReport.h"
29 #include "dialog/info.h"
30 #include "dialog/scaletile.h"
31 #include "dialog/rotatetile.h"
32 #include "dialog/alert.h"
33 #include "drawing.h"
34 #include "colorname.h"
35 #include "zq/render.h"
36 #include "zinfo.h"
37 #include <fmt/format.h>
38 #include <functional>
39 #include "zq/moveinfo.h"
40 using std::set;
41
42
43 #ifdef _MSC_VER
44 #define stricmp _stricmp
45 #endif
46
47 #define HIDE_USED (show_only_unused_tiles&1)
48 #define HIDE_UNUSED (show_only_unused_tiles&2)
49 #define HIDE_BLANK (show_only_unused_tiles&4)
50 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
51
52 extern void large_dialog(DIALOG *d);
53 static void massRecolorReset4Bit();
54 static void massRecolorReset8Bit();
55 static bool massRecolorSetup(int32_t cset);
56 static void massRecolorApply(int32_t tile);
57 extern int32_t last_droplist_sel;
58 extern int32_t TilePgCursorCol, CmbPgCursorCol;
59
60 int32_t ex=0;
61 int32_t nextcombo_fake_click=0;
62 int32_t invcol=0;
63 int32_t tthighlight = 1;
64 int32_t showcolortip = 1;
65 int32_t show_quartgrid = 0, hide_grid = 0;
66
67 tiledata *newundotilebuf;
68 std::vector<newcombo> undocombobuf;
69
70 BITMAP *selection_pattern;
71 byte selection_grid[18][18];
72 byte selection_anchor=0;
73
74 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
75 BITMAP *selecting_pattern;
76 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
77
78 extern int32_t bidcomboscripts_cnt;
79 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
80
81 BITMAP *intersection_pattern;
82
83 byte relational_template[48][4]=
84 {
85 { 0, 0, 0, 0 },
86 { 0, 1, 0, 0 },
87 { 1, 0, 0, 0 },
88 { 1, 1, 0, 0 },
89 { 0, 0, 1, 0 },
90 { 0, 1, 1, 0 },
91 { 1, 0, 1, 0 },
92 { 1, 1, 1, 0 },
93 { 0, 0, 0, 1 },
94 { 0, 1, 0, 1 },
95 { 1, 0, 0, 1 },
96 { 1, 1, 0, 1 },
97 { 0, 0, 1, 1 },
98 { 0, 1, 1, 1 },
99 { 1, 0, 1, 1 },
100 { 1, 1, 1, 1 },
101 { 0, 2, 0, 2 },
102 { 1, 2, 0, 2 },
103 { 0, 2, 1, 2 },
104 { 1, 2, 1, 2 },
105 { 3, 3, 0, 0 },
106 { 3, 3, 1, 0 },
107 { 3, 3, 0, 1 },
108 { 3, 3, 1, 1 },
109 { 3, 4, 0, 2 },
110 { 3, 4, 1, 2 },
111 { 2, 0, 2, 0 },
112 { 2, 1, 2, 0 },
113 { 2, 0, 2, 1 },
114 { 2, 1, 2, 1 },
115 { 2, 2, 2, 2 },
116 { 4, 3, 2, 0 },
117 { 4, 3, 2, 1 },
118 { 4, 4, 2, 2 },
119 { 0, 0, 3, 3 },
120 { 0, 1, 3, 3 },
121 { 1, 0, 3, 3 },
122 { 1, 1, 3, 3 },
123 { 0, 2, 3, 4 },
124 { 1, 2, 3, 4 },
125 { 3, 3, 3, 3 },
126 { 3, 4, 3, 4 },
127 { 2, 0, 4, 3 },
128 { 2, 1, 4, 3 },
129 { 2, 2, 4, 4 },
130 { 4, 3, 4, 3 },
131 { 4, 4, 4, 4 },
132 { 5, 5, 5, 5 }
133 };
134
135 byte dungeon_carving_template[96][4]=
136 {
137 { 0, 0, 0, 0 },
138 { 0, 1, 0, 0 },
139 { 1, 0, 0, 0 },
140 { 1, 1, 0, 0 },
141 { 0, 0, 1, 0 },
142 { 0, 1, 1, 0 },
143 { 1, 0, 1, 0 },
144 { 1, 1, 1, 0 },
145 { 0, 0, 0, 1 },
146 { 0, 1, 0, 1 },
147 { 1, 0, 0, 1 },
148 { 1, 1, 0, 1 },
149 { 0, 0, 1, 1 },
150 { 0, 1, 1, 1 },
151 { 1, 0, 1, 1 },
152 { 1, 1, 1, 1 },
153 { 0, 2, 0, 2 },
154 { 1, 2, 0, 2 },
155 { 0, 2, 1, 2 },
156 { 1, 2, 1, 2 },
157 { 3, 3, 0, 0 },
158 { 3, 3, 1, 0 },
159 { 3, 3, 0, 1 },
160 { 3, 3, 1, 1 },
161 { 3, 4, 0, 2 },
162 { 3, 4, 1, 2 },
163 { 2, 0, 2, 0 },
164 { 2, 1, 2, 0 },
165 { 2, 0, 2, 1 },
166 { 2, 1, 2, 1 },
167 { 2, 2, 2, 2 },
168 { 4, 3, 2, 0 },
169 { 4, 3, 2, 1 },
170 { 4, 4, 2, 2 },
171 { 0, 0, 3, 3 },
172 { 0, 1, 3, 3 },
173 { 1, 0, 3, 3 },
174 { 1, 1, 3, 3 },
175 { 0, 2, 3, 4 },
176 { 1, 2, 3, 4 },
177 { 3, 3, 3, 3 },
178 { 3, 4, 3, 4 },
179 { 2, 0, 4, 3 },
180 { 2, 1, 4, 3 },
181 { 2, 2, 4, 4 },
182 { 4, 3, 4, 3 },
183 { 4, 4, 4, 4 },
184 { 5, 5, 5, 5 },
185
186 { 5, 5, 5, 5 },
187 { 6, 6, 6, 6 },
188 { 7, 7, 7, 7 },
189 { 7, 6, 7, 6 },
190 { 8, 8, 8, 8 },
191 { 16, 6, 8, 15 },
192 { 7, 7, 8, 8 },
193 { 7, 6, 8, 15 },
194 { 9, 9, 9, 9 },
195 { 6, 6, 9, 9 },
196 { 7, 17, 14, 9 },
197 { 7, 6, 14, 9 },
198 { 8, 9, 8, 9 },
199 { 16, 6, 8, 9 },
200 { 7, 17, 8, 9 },
201 { 7, 6, 8, 9 },
202 { 10, 10, 10, 10 },
203 { 7, 10, 14, 10 },
204 { 16, 10, 8, 10 },
205 { 7, 10, 8, 10 },
206 { 11, 11, 11, 11 },
207 { 11, 11, 8, 15 },
208 { 11, 11, 14, 9 },
209 { 11, 11, 8, 9 },
210 { 14, 14, 14, 14 },
211 { 14, 14, 8, 14 },
212 { 12, 12, 12, 12 },
213 { 12, 6, 12, 15 },
214 { 12, 17, 12, 9 },
215 { 12, 6, 12, 9 },
216 { 12, 10, 12, 10 },
217 { 15, 15, 15, 15 },
218 { 15, 15, 15, 9 },
219 { 15, 14, 12, 10 },
220 { 13, 13, 13, 13 },
221 { 16, 6, 13, 13 },
222 { 7, 17, 13, 13 },
223 { 7, 6, 13, 13 },
224 { 16, 16, 16, 16 },
225 { 7, 16, 16, 16 },
226 { 11, 11, 13, 13 },
227 { 11, 14, 13, 16 },
228 { 17, 17, 17, 17 },
229 { 17, 6, 17, 17 },
230 { 12, 10, 17, 16 },
231 { 15, 11, 17, 13 },
232 { 15, 14, 17, 16 },
233 { 18, 18, 18, 18 }
234 };
235
236 struct tile_move_data
237 {
238 int32_t copies;
239 int32_t dest_first;
240 int32_t dest_last;
241 int32_t src_first;
242 int32_t src_last;
243 int32_t dest_top;
244 int32_t dest_bottom;
245 int32_t src_top;
246 int32_t src_bottom;
247 int32_t src_left, src_right;
248 int32_t src_width, src_height;
249 int32_t dest_left, dest_right;
250 int32_t dest_width, dest_height;
251 int32_t rows, cols;
252 bool rect, move;
253
254 tile_move_data()
255 {
256 copies = dest_first = dest_last = src_first = src_last = dest_top =
257 dest_bottom = src_top = src_bottom = src_left = src_right =
258 src_width = src_height = dest_left = dest_right = dest_width =
259 dest_height = rows = cols = 0;
260 rect = move = false;
261 }
262
263 tile_move_data(tile_move_data const& other)
264 {
265 copy(other);
266 }
267
268 tile_move_data& operator=(tile_move_data const& other)
269 {
270 copy(other);
271 return *this;
272 }
273
274 void copy(tile_move_data const& other)
275 {
276 copies = other.copies;
277 dest_first = other.dest_first;
278 dest_last = other.dest_last;
279 src_first = other.src_first;
280 src_last = other.src_last;
281 dest_top = other.dest_top;
282 dest_bottom = other.dest_bottom;
283 src_top = other.src_top;
284 src_bottom = other.src_bottom;
285 src_left = other.src_left;
286 src_right = other.src_right;
287 src_width = other.src_width;
288 src_height = other.src_height;
289 dest_left = other.dest_left;
290 dest_right = other.dest_right;
291 dest_width = other.dest_width;
292 dest_height = other.dest_height;
293 rows = other.rows;
294 cols = other.cols;
295 rect = other.rect;
296 move = other.move;
297 }
298
299 void flip()
300 {
301 zc_swap(src_first, dest_first);
302 zc_swap(src_last, dest_last);
303 zc_swap(src_top, dest_top);
304 zc_swap(src_bottom, dest_bottom);
305 zc_swap(src_left, dest_left);
306 zc_swap(src_right, dest_right);
307 zc_swap(src_width, dest_width);
308 zc_swap(src_height, dest_height);
309 }
310 };
311 bool do_movetile_united(tile_move_data const& tmd);
312
313 struct combo_move_data
314 {
315 int32_t tile, tile2, copy1, copycnt;
316 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
317 combo_move_data(combo_move_data const& other)
318 {
319 copy(other);
320 }
321 combo_move_data& operator=(combo_move_data const& other)
322 {
323 copy(other);
324 return *this;
325 }
326 void copy(combo_move_data const& other)
327 {
328 tile = other.tile;
329 tile2 = other.tile2;
330 copy1 = other.copy1;
331 copycnt = other.copycnt;
332 }
333
334 void flip()
335 {
336 int32_t tcnt = tile2-tile+1;
337 int32_t cpy2 = copy1+copycnt-1;
338 zc_swap(tile,copy1);
339 tile2 = cpy2;
340 copycnt = tcnt;
341 }
342 };
343
344 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
345 static optional<ComboMoveUndo> last_combo_move_list;
346 static optional<TileMoveUndo> last_tile_move_list;
347
348 int refl_flags = 0;
349 enum
350 {
351 REFL_90CW, REFL_HFLIP,
352 REFL_90CCW, REFL_VFLIP,
353 REFL_180, REFL_DBLFLIP,
354 REFL_MAX
355 };
356 const char *reflbtn_names[] =
357 {
358 "90 CW", "HFlip",
359 "90 CCW", "VFlip",
360 "180 Rot", "Diag Flip"
361 };
362 int bgmode = 0, xmode = 0;
363 const char *bgmodebtn_names[] =
364 {
365 "BG Color 0", "BG Trans."
366 };
367 const char *xmodebtn_names[] =
368 {
369 "X", "No X"
370 };
371 enum
372 {
373 XMODE_X, XMODE_NOX,
374 XMODE_MAX
375 };
376 enum
377 {
378 BGMODE_0, BGMODE_TRANSP,
379 BGMODE_MAX
380 };
381
382 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
383 {
384 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
385 int32_t size2=size>>1;
386
387 if(newtilebuf[dest_tile].data==NULL)
388 {
389 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
390 }
391
392 int32_t i=0;
393
394 if((dest_tile<<2)+i!=src_quarter1)
395 {
396 for(int32_t j=0; j<8; ++j)
397 {
398 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
399 }
400 }
401
402 i=1;
403
404 if((dest_tile<<2)+i!=src_quarter2)
405 {
406 for(int32_t j=0; j<8; ++j)
407 {
408 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
409 }
410 }
411
412 i=2;
413
414 if((dest_tile<<2)+i!=src_quarter3)
415 {
416 for(int32_t j=0; j<8; ++j)
417 {
418 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
419 }
420 }
421
422 i=3;
423
424 if((dest_tile<<2)+i!=src_quarter4)
425 {
426 for(int32_t j=0; j<8; ++j)
427 {
428 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
429 }
430 }
431 }
432
433 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
434 {
435 al_trace("inside make_combos()\n");
436 int32_t startCombo=0;
437
438 if(!select_combo_2(startCombo,cs))
439 return;
440
441 int32_t temp=combobuf[startCombo].o_tile;
442 combobuf[startCombo].set_tile(startTile);
443
444 if(!edit_combo(startCombo, false, cs))
445 {
446 combobuf[startCombo].set_tile(temp);
447 return;
448 }
449
450 go_combos();
451
452 for(int32_t i=0; i<=endTile-startTile; i++)
453 {
454 combobuf[startCombo+i]=combobuf[startCombo];
455 combobuf[startCombo+i].set_tile(startTile+i);
456 }
457
458 setup_combo_animations();
459 setup_combo_animations2();
460 }
461
462 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
463 {
464 int32_t startCombo=0;
465
466 if(!select_combo_2(startCombo, cs))
467 return;
468
469 int32_t startTile=top*TILES_PER_ROW+left;
470 int32_t temp=combobuf[startCombo].o_tile;
471 combobuf[startCombo].set_tile(startTile);
472
473 if(!edit_combo(startCombo, false, cs))
474 {
475 al_trace("make_combos_rect() early return\n");
476 combobuf[startCombo].set_tile(temp);
477 return;
478 }
479
480 bool smartWrap=false;
481 if(numCols!=4 && numRows>1)
482 {
483 char buf[64];
484 if(numCols<4)
485 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
486 else
487 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
488 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
489 if(ret==1)
490 smartWrap=true;
491 }
492
493 go_combos();
494
495 int32_t combo=startCombo-1;
496 for(int32_t row=0; row<numRows; row++)
497 {
498 for(int32_t col=0; col<numCols; col++)
499 {
500 int32_t tile=startTile+row*TILES_PER_ROW+col;
501 if(smartWrap)
502 // Add 4 per row, and another numRows*4 for every 4 columns
503 // (col&0xFC==col/4*4), and then the column %4
504 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
505 else
506 combo++;
507
508 combobuf[combo]=combobuf[startCombo];
509 combobuf[combo].set_tile(tile);
510 }
511 }
512
513 setup_combo_animations();
514 setup_combo_animations2();
515 }
516
517 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
518
519 static bool nogotiles = false;
520 static bool nogocombos = false;
521
522 void go_tiles()
523 {
524 if(nogotiles) return;
525 last_tile_move_list = nullopt;
526 for(int32_t i=0; i<NEWMAXTILES; ++i)
527 {
528 newundotilebuf[i].format=newtilebuf[i].format;
529
530 if(newundotilebuf[i].data!=NULL)
531 {
532 free(newundotilebuf[i].data);
533 }
534
535 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
536
537 if(newundotilebuf[i].data==NULL)
538 {
539 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
540 }
541
542 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
543 }
544 }
545
546 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
547 {
548 for(int32_t c=0; c<columns; c++)
549 {
550 for(int32_t r=0; r<rows; r++)
551 {
552 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
553 newundotilebuf[t].format=newtilebuf[t].format;
554
555 if(newundotilebuf[t].data!=NULL)
556 {
557 free(newundotilebuf[t].data);
558 }
559
560 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
561
562 if(newundotilebuf[t].data==NULL)
563 {
564 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
565 }
566
567 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
568 }
569 }
570 }
571
572 void comeback_tiles()
573 {
574 if(last_tile_move_list)
575 {
576 last_tile_move_list->undo();
577 last_tile_move_list = nullopt;
578 }
579 for(dword i=0; i<NEWMAXTILES; ++i)
580 {
581 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
582 {
583 newtilebuf[i].format = newundotilebuf[i].format;
584
585 if(newtilebuf[i].data!=NULL)
586 free(newtilebuf[i].data);
587 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
588 if(newtilebuf[i].data==NULL)
589 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
590 }
591
592 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
593 }
594
595 register_blank_tiles();
596 register_used_tiles();
597 }
598
599 void go_combos()
600 {
601 if(nogocombos) return;
602 last_combo_move_list = nullopt;
603
604 undocombobuf = combobuf;
605 }
606
607 void comeback_combos()
608 {
609 if(last_combo_move_list)
610 {
611 last_combo_move_list->undo();
612 last_combo_move_list = nullopt;
613 }
614
615 combobuf = undocombobuf;
616 }
617
618 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
619 {
620 line(dest,x,y,x+s,y+s,c);
621 line(dest,x+s,y,x,y+s,c);
622 }
623 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
624 {
625 line(dest,x,y,x+w,y+h,c);
626 line(dest,x+w,y,x,y+h,c);
627 }
628
629 enum {gm_light, gm_dark, gm_max};
630 int32_t gridmode=gm_light;
631
632 bool has_selection()
633 {
634 for(int32_t i=1; i<17; ++i)
635 {
636 for(int32_t j=1; j<17; ++j)
637 {
638 if(selection_grid[i][j])
639 {
640 return true;
641 }
642 }
643 }
644
645 return false;
646 }
647
648 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
649 {
650 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
651
652 for(int32_t i=1; i<18; ++i)
653 {
654 for(int32_t j=1; j<18; ++j)
655 {
656 // zoomtile16(screen2,tile,79,31,cs,flip,8);
657 if(selection_grid[i-1][j]!=selection_grid[i][j])
658 {
659 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
660 }
661
662 if(selection_grid[i][j-1]!=selection_grid[i][j])
663 {
664 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
665 }
666 }
667 }
668
669 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
670 // selection_anchor=(selection_anchor+1)%64;
671 }
672
673 bool is_selecting()
674 {
675 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
676 }
677
678 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
679 {
680 int32_t x1=zc_min(selecting_x1,selecting_x2);
681 int32_t x2=zc_max(selecting_x1,selecting_x2);
682 int32_t y1=zc_min(selecting_y1,selecting_y2);
683 int32_t y2=zc_max(selecting_y1,selecting_y2);
684
685 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
686 for(int32_t i=1; i<18; ++i)
687 {
688 for(int32_t j=1; j<18; ++j)
689 {
690 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
691
692 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
693 {
694 if(selection_grid[i-1][j]!=selection_grid[i][j])
695 {
696 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
697 }
698
699 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
700 }
701
702 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
703 {
704 if(selection_grid[i][j-1]!=selection_grid[i][j])
705 {
706 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
707 }
708
709 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
710 }
711 }
712 }
713
714 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
715 // selection_anchor=(selection_anchor+1)%64;
716 }
717
718 void unfloat_selection();
719 bool floating_sel = false;
720 byte floatsel[256];
721 byte undofloatsel[256];
722 bool undo_is_floatsel = false;
723
724
725 void add_color_to_selection(int32_t color)
726 {
727 unfloat_selection();
728 for(int32_t i=1; i<17; ++i)
729 {
730 for(int32_t j=1; j<17; ++j)
731 {
732 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
733 {
734 selection_grid[i][j]=1;
735 }
736 }
737 }
738 }
739
740 void remove_color_from_selection(int32_t color)
741 {
742 unfloat_selection();
743 for(int32_t i=1; i<17; ++i)
744 {
745 for(int32_t j=1; j<17; ++j)
746 {
747 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
748 {
749 selection_grid[i][j]=0;
750 }
751 }
752 }
753 }
754
755 void intersect_color_with_selection(int32_t color)
756 {
757 unfloat_selection();
758 for(int32_t i=1; i<17; ++i)
759 {
760 for(int32_t j=1; j<17; ++j)
761 {
762 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
763 {
764 selection_grid[i][j]=1;
765 }
766 else
767 {
768 selection_grid[i][j]=0;
769 }
770 }
771 }
772 }
773
774 bool is_in_selection(int32_t x, int32_t y)
775 {
776 x %= 16; y %= 16;
777 if(x < 0) x = (16 - abs(x));
778 if(y < 0) y = (16 - abs(y));
779 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
780 }
781
782 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
783 {
784 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
785 int gridcol = gridmode==gm_light?vc(7):vc(8);
786
787 cset <<= 4;
788 if(newtilebuf[tile].format>tf4Bit)
789 cset=0;
790
791 int g = hide_grid ? 1 : 0;
792 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
793 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
794
795 unpack_tile(newtilebuf, tile, 0, false);
796 byte *si = unpackbuf;
797 for(int32_t cy=0; cy<16; cy++)
798 {
799 for(int32_t cx=0; cx<16; cx++)
800 {
801 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
802 int32_t dx = ((flip&1)?15-cx:cx)*m;
803 int32_t dy = ((flip&2)?15-cy:cy)*m;
804 if(col)
805 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
806
807 if(!col && xmode == XMODE_X)
808 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
809
810 ++si;
811 }
812 }
813
814 if(!hide_grid)
815 {
816 for(int cx = 0; cx <= 16; ++cx)
817 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
818 for(int cy = 0; cy <= 16; ++cy)
819 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
820 }
821
822 if(show_quartgrid)
823 {
824 int offs = (8*m);
825 const int RAD = 3;
826 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
827 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
828 }
829
830 if(has_selection()||is_selecting())
831 {
832 selection_anchor=(selection_anchor+1)%64;
833
834 if(has_selection()||is_selecting())
835 draw_selection_outline(dest, x, y, m);
836
837 if(is_selecting())
838 draw_selecting_outline(dest, x, y, m);
839 }
840 }
841
842 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
843 {
844 if(!jwin)
845 {
846 if(flags&D_SELECTED)
847 {
848 zc_swap(fg,bg);
849 }
850
851 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
852 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
853 rect(dest,x,y,x+w-2,y+h-2,fg);
854 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
855 }
856 else
857 {
858 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
859 }
860 }
861
862 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
863 {
864 if(!jwin)
865 {
866 if(flags&D_SELECTED)
867 {
868 zc_swap(fg,bg);
869 }
870
871 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
872 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
873 rect(dest,x,y,x+w-2,y+h-2,fg);
874 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
875 }
876 else
877 {
878 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
879 }
880 }
881
882 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
883 {
884 if(flags&D_SELECTED)
885 {
886 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
887 ++x;
888 ++y;
889 --w;
890 --h;
891 }
892 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
893 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
894
895 //Forcibly fit the text within the button
896 char buf[512] = {0};
897 strcpy(buf, text);
898
899 bool dis = (flags&D_DISABLED);
900 auto hei = text_height(font);
901 auto len = text_length(font,buf);
902 auto borderwid = 8;
903 if(len > w - borderwid + (dis ? 1 : 0))
904 {
905 auto ind = strlen(buf) - 1;
906 auto dotcount = 0;
907 while(len > w - borderwid + (dis ? 1 : 0))
908 {
909 if(dotcount >= 2)
910 buf[ind+2] = 0;
911 else ++dotcount;
912 buf[ind--] = '.';
913 len = text_length(font,buf);
914 }
915 }
916 if(dis)
917 {
918 ++len; ++hei;
919 }
920 BITMAP* tmp = create_bitmap_ex(8,len,hei);
921 clear_bitmap(tmp);
922 if(dis)
923 {
924 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
925 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
926 }
927 else
928 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
929 auto tx = x+((w-len)/2);
930 auto ty = y+((h-hei)/2);
931 if(len > w-borderwid)
932 {
933 tx = x+borderwid/2;
934 len = w-borderwid;
935 }
936 if(hei > h-borderwid)
937 {
938 ty = y+borderwid/2;
939 hei = h-borderwid;
940 }
941 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
942 destroy_bitmap(tmp);
943 }
944
945 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
946 {
947 bool over=false;
948
949 while(gui_mouse_b())
950 {
951 //vsync();
952 if(mouse_in_rect(x,y,w,h))
953 {
954 if(!over)
955 {
956 vsync();
957 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
958 over=true;
959
960 update_hw_screen();
961 }
962 }
963 else
964 {
965 if(over)
966 {
967 vsync();
968 draw_layer_button(screen, x, y, w, h, text, flags);
969 over=false;
970
971 update_hw_screen();
972 }
973 }
974 rest(1);
975 }
976
977 if(over)
978 {
979 vsync();
980 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
981
982 update_hw_screen();
983 }
984
985 return over;
986 }
987
988 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
989 {
990 bool over=false;
991
992 while(gui_mouse_b())
993 {
994 custom_vsync();
995
996 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
997 {
998 if(!over)
999 {
1000 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1001 over=true;
1002 }
1003 }
1004 else
1005 {
1006 if(over)
1007 {
1008 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1009 over=false;
1010 }
1011 }
1012 }
1013
1014 if(over)
1015 {
1016 custom_vsync();
1017 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1018 }
1019
1020 return over;
1021 }
1022
1023 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1024 {
1025 if(!jwin)
1026 {
1027 if(flags&D_SELECTED)
1028 {
1029 zc_swap(fg,bg);
1030 }
1031
1032 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1033 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1034 rect(dest,x,y,x+w-2,y+h-2,fg);
1035 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1036
1037 if(overlay)
1038 {
1039 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1040 }
1041 else
1042 {
1043 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1044 }
1045 }
1046 else
1047 {
1048 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1049 }
1050 }
1051
1052 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1053 {
1054 bool over=false;
1055
1056 while(gui_mouse_b())
1057 {
1058 custom_vsync();
1059
1060 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1061 {
1062 if(!over)
1063 {
1064 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1065 over=true;
1066 }
1067 }
1068 else
1069 {
1070 if(over)
1071 {
1072 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1073 over=false;
1074 }
1075 }
1076 }
1077
1078 return over;
1079 }
1080
1081 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1082 {
1083 bool over=false;
1084
1085 while(gui_mouse_b())
1086 {
1087 custom_vsync();
1088
1089 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1090 {
1091 if(!over)
1092 {
1093 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1094 over=true;
1095 }
1096 }
1097 else
1098 {
1099 if(over)
1100 {
1101 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1102 over=false;
1103 }
1104 }
1105 }
1106
1107 if(over)
1108 {
1109 custom_vsync();
1110 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1111 }
1112
1113 return over;
1114 }
1115 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1116 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1117
1118 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1119 {
1120 //these are here to bypass compiler warnings about unused arguments
1121 bg=bg;
1122 fg=fg;
1123
1124 int32_t r, center;
1125
1126 for(int32_t k=0; k<7; k++)
1127 {
1128 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1129 {
1130 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1131 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1132 //*
1133 r = 9/2;
1134
1135 center = x+(k*25)+r;
1136 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1137
1138 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1139 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1140 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1141 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1142 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1143
1144 if(value==k)
1145 {
1146 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1147 }
1148
1149 //*/
1150 }
1151 }
1152 }
1153
1154 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1155 {
1156 while(gui_mouse_b())
1157 {
1158 custom_vsync();
1159
1160 for(int32_t k=0; k<7; k++)
1161 {
1162 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1163 {
1164 //if on radio button
1165 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1166 {
1167 value=k;
1168 draw_layerradio(dest,x,y,bg,fg,value);
1169 refresh(rMENU);
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1176 //*************** tile flood fill stuff **************
1177
1178 byte tf_c;
1179 byte tf_u;
1180
1181 void tile_floodfill_rec(int32_t x,int32_t y)
1182 {
1183 if(is_in_selection(x,y))
1184 {
1185 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1186 --x;
1187
1188 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1189 {
1190 if(is_in_selection(x,y))
1191 {
1192 unpackbuf[(y<<4)+x] = tf_c;
1193 }
1194
1195 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1196 tile_floodfill_rec(x,y-1);
1197
1198 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1199 tile_floodfill_rec(x,y+1);
1200
1201 ++x;
1202 }
1203 }
1204 }
1205
1206 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1207 {
1208 if(is_in_selection(x,y))
1209 {
1210 if(floating_sel)
1211 {
1212 memcpy(unpackbuf, floatsel, 256);
1213 }
1214 else unpack_tile(newtilebuf, tile, 0, false);
1215 tf_c = c;
1216 tf_u = unpackbuf[(y<<4)+x];
1217
1218 if(tf_u != tf_c)
1219 tile_floodfill_rec(x,y);
1220 if(floating_sel)
1221 {
1222 memcpy(floatsel, unpackbuf, 256);
1223 }
1224 else pack_tile(newtilebuf,unpackbuf,tile);
1225 }
1226 }
1227
1228 //***************** tile editor stuff *****************
1229 12 size_and_pos ok_button(302,562,71,21);
1230 12 size_and_pos cancel_button(376,562,71,21);
1231 12 size_and_pos edit_button(550,562,86,21);
1232 12 size_and_pos hlcbox(742,392,16,16);
1233 12 size_and_pos hov_prev(742,338,50,50);
1234 12 size_and_pos cpalette_4(648,416,4,4,64,64);
1235 12 size_and_pos cpalette_8(648,416,16,14,16,18);
1236 12 size_and_pos fg_prev(648,316,50,50);
1237 12 size_and_pos bg_prev(648+30,316+30,50,50);
1238 12 size_and_pos zoomtile(124,32,16,16,32,32);
1239 12 size_and_pos prev_til_1(648,31,96,96);
1240 12 size_and_pos prev_til_2(752,31,96,96);
1241 12 size_and_pos prev_til_3(648,135,96,96);
1242 12 size_and_pos prev_til_4(752,135,96,96);
1243 12 size_and_pos ref_til(14,189,96,96);
1244 12 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1245 12 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1246 12 size_and_pos color_info(4,294,1,1,116,8);
1247 12 size_and_pos color_info_btn(24,294,96,21);
1248 12 size_and_pos tool_btns(22,29,2,4,39,39);
1249 12 size_and_pos x_btn(890,5,15,13);
1250 12 size_and_pos info_btn(872,5,15,13);
1251 12 size_and_pos hidegrid_cbox(124,552,16,16);
1252 12 size_and_pos quartgrid_cbox(124,572,16,16);
1253 12 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1254 12 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1255 12 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1256
1257 int32_t c1=1;
1258 int32_t c2=0;
1259 int32_t floating_tile = -1;
1260 int32_t tool = t_pen;
1261 int32_t old_tool = -1;
1262 int32_t tool_cur = -1;
1263 int32_t select_mode = 0;
1264 int32_t drawing=0;
1265 int32_t reftile = 0;
1266
1267 bool qgrid_tool(int tool)
1268 {
1269 switch(tool)
1270 {
1271 case t_pen:
1272 case t_fill:
1273 case t_recolor:
1274 case t_wand:
1275 return true;
1276 }
1277 return false;
1278 }
1279
1280 void set_tool_sprite(int tool, int type)
1281 {
1282 int spr = ZQM_NORMAL;
1283 switch(tool)
1284 {
1285 case t_pen: spr = ZQM_SWORD; break;
1286 case t_fill: spr = ZQM_POTION; break;
1287 case t_recolor: spr = ZQM_WAND; break;
1288 case t_eyedropper: spr = ZQM_LENS; break;
1289 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1290 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1291 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1292 }
1293 MouseSprite::set(spr);
1294 }
1295 void update_tool_cursor()
1296 {
1297 int32_t temp_mouse_x=gui_mouse_x();
1298 int32_t temp_mouse_y=gui_mouse_y();
1299
1300 int32_t type=0;
1301
1302 if(has_selection())
1303 {
1304 switch(tool)
1305 {
1306 case t_select:
1307 case t_wand:
1308 type+=select_mode;
1309 break;
1310 }
1311 }
1312
1313 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1314 {
1315 if(tool_cur==-1)
1316 set_tool_sprite(tool,type);
1317
1318 tool_cur=tool;
1319 }
1320 else if(tool_cur != -1)
1321 {
1322 MouseSprite::set(ZQM_NORMAL);
1323 tool_cur = -1;
1324 }
1325 }
1326
1327 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile,bool create_tbar)
1328 {
1329 PALETTE tpal;
1330 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1331 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1332 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1333
1334 if(!create_tbar)
1335 {
1336 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1337 }
1338 else
1339 {
1340 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1341 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1342 }
1343
1344 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1345
1346 clear_to_color(preview_bmp, 0);
1347
1348 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1349 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1350 puttile16(preview_bmp,tile,0,0,cs,flip);
1351 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1352
1353 clear_to_color(preview_bmp, 0);
1354 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1355 overtile16(preview_bmp,tile,0,0,cs,flip);
1356 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1357 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1358
1359 unpack_tile(newtilebuf, tile, 0, true);
1360 if(floating_sel)
1361 for(auto q = 0; q < 256; ++q)
1362 if(floatsel[q])
1363 unpackbuf[q] = floatsel[q];
1364 byte tmptile[256];
1365 byte *tmpptr = tmptile;
1366 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1367 pack_tile(newtilebuf,unpackbuf,tile);
1368 clear_to_color(preview_bmp, 0);
1369
1370 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1371 puttile16(preview_bmp,tile,0,0,cs,flip);
1372 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1373
1374 clear_to_color(preview_bmp, 0);
1375 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1376 overtile16(preview_bmp,tile,0,0,cs,flip);
1377 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1378
1379 if(reftile > 0)
1380 {
1381 clear_to_color(preview_bmp, 0);
1382 jwin_draw_win(screen2, ref_til.x-2,ref_til.y-2, ref_til.w+4, ref_til.h+4, FR_DEEP);
1383 overtile16(preview_bmp,reftile,0,0,cs,flip);
1384 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, ref_til.x, ref_til.y, ref_til.w, ref_til.h);
1385 }
1386
1387 //Color info
1388 {
1389 color_info.h = 1;
1390 if(showcolortip)
1391 {
1392 auto fh = color_info.yscale = text_height(font);
1393 int ty = color_info.y;
1394 if(reftile <= 0)
1395 ty -= ref_til.h + 8;
1396 int y = ty;
1397 int rx = color_info.x+color_info.xscale;
1398 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1399 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1400 auto str = get_tile_colornames(tile,cs);
1401 size_t pos = 0;
1402 char buf[512] = {0};
1403 char cbuf[16] = {0};
1404 while(pos < str.size())
1405 {
1406 y += fh;
1407 if(y+fh > zq_screen_h)
1408 break; //Out of space!
1409 auto endpos = str.find_first_of('\n',pos);
1410
1411 if(endpos == std::string::npos)
1412 {
1413 strcpy(buf,str.substr(pos).c_str());
1414 pos = str.size();
1415 }
1416 else
1417 {
1418 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1419 pos = endpos+1;
1420 }
1421 //Ensure the name fits horizontally
1422 if(text_length(font,buf) > color_info.xscale)
1423 {
1424 size_t pos = 0;
1425 for(; buf[pos]; ++pos)
1426 {
1427 if(buf[pos] == ':')
1428 {
1429 strcpy(cbuf, buf+pos);
1430 buf[pos] = 0;
1431 break;
1432 }
1433 }
1434 size_t clen = text_length(font,cbuf);
1435 size_t dotlen = text_length(font,"..");
1436
1437 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1438 buf[--pos] = 0;
1439 while(buf[pos] == ' ')
1440 buf[pos] = 0;
1441 strcat(buf,"..");
1442 strcat(buf,cbuf);
1443 }
1444 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1445 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1446 ++color_info.h;
1447 }
1448 jwin_draw_frame(screen2,color_info.x-2,ty-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1449 }
1450 else
1451 {
1452 int ty = color_info_btn.y;
1453 if(reftile <= 0)
1454 ty -= ref_til.h + 8;
1455 draw_text_button(screen2,color_info_btn.x,ty,color_info_btn.w,color_info_btn.h,
1456 "Show Colors",vc(1),vc(14),0,true);
1457 }
1458 }
1459
1460 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1461
1462 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1463 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1464
1465 if(floating_sel)
1466 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1467 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1468 if(newtilebuf[tile].format==tf8Bit)
1469 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1470 else
1471 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1472
1473 PALETTE temppal;
1474
1475 //palette and mouse
1476 switch(newtilebuf[tile].format)
1477 {
1478 case tf4Bit:
1479 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1480 get_palette(temppal);
1481
1482 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1483 {
1484 size_and_pos const& s = cpalette_4.subsquare(i);
1485 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1486 }
1487
1488 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1489 break;
1490
1491 case tf8Bit:
1492 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1493
1494 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1495 {
1496 size_and_pos const& s = cpalette_8.subsquare(i);
1497 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1498 }
1499
1500 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1501 break;
1502 }
1503
1504 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1505 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1506 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1507
1508 if(c2==0)
1509 {
1510 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1511 }
1512
1513 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1514 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1515 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1516
1517 if(c1==0)
1518 {
1519 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1520 }
1521
1522 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1523 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1524 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1525 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1526 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1527
1528 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1529 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1530
1531 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1532 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1533
1534 bool qgrd = show_quartgrid && qgrid_tool(tool);
1535 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1536 for(int q = 0; q < REFL_MAX; ++q)
1537 {
1538 auto& sqr = reflbtn_grid.subsquare(q);
1539 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1540 }
1541 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1542 for(int q = 0; q < XMODE_MAX; ++q)
1543 {
1544 auto& sqr = xmodebtn_grid.subsquare(q);
1545 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1546 }
1547 for(int q = 0; q < BGMODE_MAX; ++q)
1548 {
1549 auto& sqr = bgmodebtn_grid.subsquare(q);
1550 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1551 }
1552
1553 //tool buttons
1554 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1555 {
1556 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1557 int col = toolbtn%tool_btns.w;
1558 int row = toolbtn/tool_btns.w;
1559
1560 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1561 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1562 }
1563
1564 //coordinates
1565 {
1566 auto mx = gui_mouse_x();
1567 auto my = gui_mouse_y();
1568 int32_t ind = zoomtile.rectind(mx,my);
1569 int32_t temp_x=ind%zoomtile.w;
1570 int32_t temp_y=ind/zoomtile.w;
1571 int color = -1;
1572
1573 bool is8b = newtilebuf[tile].format > tf4Bit;
1574 if(ind > -1)
1575 {
1576 char xbuf[16];
1577 sprintf(xbuf, "x: %d", temp_x);
1578 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1579 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1580 unpack_tile(newtilebuf, tile, 0, false);
1581 byte *si = unpackbuf;
1582 si+=ind;
1583 color = *si;
1584 }
1585 else if(fg_prev.rect(mx,my))
1586 color = c1;
1587 else if(bg_prev.rect(mx,my))
1588 color = c2;
1589 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1590 if(color > -1)
1591 {
1592 get_palette(tpal);
1593 char separator = ' ';
1594 char buf[512] = {0};
1595
1596 int realcol = color+(is8b?0:CSET(cs));
1597 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1598 auto& c = tpal[realcol];
1599
1600 if(tthighlight)
1601 {
1602 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1603 size_and_pos const& csqr = mainsqr.subsquare(color);
1604
1605 int hlcol = getHighlightColor(tpal[realcol]);
1606 int hlthick = 4;
1607 int extraborder = is8b ? 8 : 0;
1608 int borderthick = hlthick+extraborder;
1609
1610 if(is8b)
1611 {
1612 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1613 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1614 }
1615 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1616 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1617 if(xcolor)
1618 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1619 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1620 }
1621
1622 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1623 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1624
1625 strcpy(buf, get_color_name(realcol, is8b).c_str());
1626 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1627
1628 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1629 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1630
1631 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1632 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1633 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1634 if(xcolor)
1635 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1636 }
1637 }
1638
1639 custom_vsync();
1640 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1641 update_tool_cursor();
1642 SCRFIX();
1643 }
1644
1645 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1646 {
1647 unfloat_selection();
1648 if(tile>tile2)
1649 {
1650 zc_swap(tile, tile2);
1651 }
1652
1653 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1654 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1655
1656 int32_t start=tile;
1657 int32_t end=tile2;
1658
1659 // Might have top-right and bottom-left corners selected...
1660 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1661 {
1662 start=tile-(TILECOL(tile)-TILECOL(tile2));
1663 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1664 }
1665
1666 for(int32_t temptile=start; temptile<=end; temptile++)
1667 {
1668 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1669 {
1670 unpack_tile(newtilebuf, temptile, 0, true);
1671
1672 if(flip&1)
1673 {
1674 for(int32_t y=0; y<16; y++)
1675 {
1676 for(int32_t x=0; x<8; x++)
1677 {
1678 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1679 }
1680 }
1681 }
1682
1683 if(flip&2)
1684 {
1685 for(int32_t y=0; y<8; y++)
1686 {
1687 for(int32_t x=0; x<16; x++)
1688 {
1689 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1690 }
1691 }
1692 }
1693
1694 pack_tile(newtilebuf,unpackbuf,temptile);
1695 }
1696 }
1697 }
1698
1699 void rotate_tile(int32_t tile, bool backward)
1700 {
1701 unfloat_selection();
1702 unpack_tile(newtilebuf, tile, 0, true);
1703 byte tempunpackbuf[256];
1704 byte tempx, tempy;
1705
1706 for(tempx=0; tempx<16; tempx++)
1707 {
1708 for(tempy=0; tempy<16; tempy++)
1709 {
1710 if(!backward)
1711 {
1712 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1713 }
1714 else
1715 {
1716 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1717 }
1718 }
1719 }
1720
1721 pack_tile(newtilebuf,tempunpackbuf,tile);
1722 }
1723
1724 static int32_t undocount=128;
1725 byte undotile[256];
1726
1727 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1728 {
1729 byte buf[256];
1730
1731 for(int32_t i=0; i<undocount; i++)
1732 {
1733 newtilebuf[tile].data[i]=undotile[i];
1734 }
1735
1736 if(!(horizontal||vertical))
1737 {
1738 return;
1739 }
1740
1741 unpack_tile(newtilebuf, tile, 0, true);
1742
1743 for(int32_t i=0; i<256; i++)
1744 {
1745 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1746 buf[shift_ind] = unpackbuf[i];
1747 }
1748
1749 if(clear)
1750 {
1751 for(int32_t r=0; r<abs(vertical); r++)
1752 {
1753 for(int32_t c=0; c<16; c++)
1754 {
1755 buf[(vertical>0?r:15-r)*16+c]=0;
1756 }
1757 }
1758
1759 for(int32_t r=0; r<16; r++)
1760 {
1761 for(int32_t c=0; c<abs(horizontal); c++)
1762 {
1763 buf[r*16+(horizontal>0?c:15-c)]=0;
1764 }
1765 }
1766 }
1767
1768 pack_tile(newtilebuf,buf,tile);
1769 }
1770
1771 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1772 {
1773 byte buf[256];
1774
1775 if(!(horizontal||vertical))
1776 {
1777 return;
1778 }
1779
1780 memset(buf,0,256);
1781
1782 for(int32_t i=0; i<256; i++)
1783 {
1784 if(is_in_selection(i%16,i/16))
1785 {
1786 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1787 buf[shift_ind] = floatsel[i];
1788 }
1789 }
1790
1791 memcpy(floatsel,buf,256);
1792 }
1793
1794 void float_selection(int32_t tile, bool clear)
1795 {
1796 if(floating_sel) return;
1797 floating_sel = true;
1798 floating_tile = tile;
1799
1800 unpack_tile(newtilebuf, tile, 0, true);
1801
1802 for(auto q = 0; q < 256; ++q)
1803 {
1804 if(is_in_selection(q%16,q/16))
1805 {
1806 floatsel[q] = unpackbuf[q];
1807 unpackbuf[q] = clear ? 0 : c2;
1808 }
1809 else floatsel[q] = 0;
1810 }
1811
1812 pack_tile(newtilebuf,unpackbuf,tile);
1813 }
1814
1815 void unfloat_selection()
1816 {
1817 if(!floating_sel) return;
1818 floating_sel = false;
1819
1820 unpack_tile(newtilebuf, floating_tile, 0, true);
1821
1822 for(auto q = 0; q < 256; ++q)
1823 {
1824 if(floatsel[q])
1825 {
1826 unpackbuf[q] = floatsel[q];
1827 }
1828 }
1829
1830 pack_tile(newtilebuf,unpackbuf,floating_tile);
1831 floating_tile = -1;
1832 }
1833
1834 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1835 {
1836 if(floating_sel)
1837 {
1838 for(auto q = 0; q < 256; ++q)
1839 {
1840 if(ignore_transparent && floatsel[q]==0)
1841 continue;
1842 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1843 }
1844 return;
1845 }
1846
1847 byte buf[256];
1848 unpack_tile(newtilebuf, tile, 0, true);
1849
1850 for(int32_t i=0; i<256; i++)
1851 {
1852 buf[i]=unpackbuf[i];
1853
1854 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1855 continue;
1856
1857 if(ignore_transparent)
1858 {
1859 if(buf[i]==0)
1860 continue;
1861
1862 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1863 }
1864 else // Don't ignore transparent
1865 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1866 }
1867
1868 pack_tile(newtilebuf,buf,tile);
1869 }
1870
1871 void clear_selection_grid()
1872 {
1873 unfloat_selection();
1874 for(int32_t x=0; x<18; ++x)
1875 {
1876 for(int32_t y=0; y<18; ++y)
1877 {
1878 selection_grid[x][y]=0;
1879 }
1880 }
1881 }
1882
1883 void invert_selection_grid()
1884 {
1885 unfloat_selection();
1886 for(int32_t x=1; x<17; ++x)
1887 {
1888 for(int32_t y=1; y<17; ++y)
1889 {
1890 selection_grid[x][y]=selection_grid[x][y]?0:1;
1891 }
1892 }
1893 }
1894
1895 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1896 {
1897 byte local_grid[16][16];
1898 memset(local_grid, 0, sizeof(local_grid));
1899 for(auto x = 0; x < 16; ++x)
1900 {
1901 for(auto y = 0; y < 16; ++y)
1902 {
1903 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1904 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1905 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1906 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1907 }
1908 }
1909 for(auto x = 0; x < 16; ++x)
1910 {
1911 for(auto y = 0; y < 16; ++y)
1912 {
1913 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1914 }
1915 }
1916 }
1917
1918 void show_edit_tile_help()
1919 {
1920 InfoDialog("Help: Tile Editor", "Hotkeys:"
1921 "\nF1: This Help Dialog"
1922 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1923 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1924 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1925 "\nH/V: Flip | (Shift+)R: Rotate"
1926 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1927 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1928 "\nF12: Screenshot (whole screen)"
1929 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1930 "\nWhen not on Select tools, hold to swap:"
1931 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1932 }
1933
1934 static int move_origin_x=-1, move_origin_y=-1;
1935 static int prev_x=-1, prev_y=-1;
1936 bool __pixel_draw(int x, int y, int tile, int flip)
1937 {
1938 bool ret = false;
1939 switch(tool)
1940 {
1941 case t_pen:
1942 if(flip&1) x=15-x;
1943
1944 if(flip&2) y=15-y;
1945
1946 if(is_in_selection(x,y))
1947 {
1948 if(floating_sel)
1949 {
1950 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1951 }
1952 else
1953 {
1954 unpack_tile(newtilebuf, tile, 0, false);
1955 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1956 pack_tile(newtilebuf, unpackbuf,tile);
1957 }
1958 }
1959 break;
1960
1961 case t_fill:
1962 if(is_in_selection(x,y))
1963 {
1964 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1965 ret = true;
1966 }
1967 break;
1968
1969 case t_recolor:
1970 if(is_in_selection(x,y))
1971 {
1972 if(floating_sel)
1973 {
1974 tf_u = floatsel[(y<<4)+x];
1975 for(int32_t i=0; i<256; i++)
1976 {
1977 if(is_in_selection(i&15,i>>4))
1978 {
1979 if(floatsel[i]==tf_u)
1980 {
1981 floatsel[i]=(drawing==1)?c1:c2;
1982 }
1983 }
1984 }
1985 }
1986 else
1987 {
1988 unpack_tile(newtilebuf, tile, 0, false);
1989 tf_u = unpackbuf[(y<<4)+x];
1990 if(tf_u != ((drawing==1)?c1:c2))
1991 {
1992 for(int32_t i=0; i<256; i++)
1993 {
1994 if(is_in_selection(i&15,i>>4))
1995 {
1996 if(unpackbuf[i]==tf_u)
1997 {
1998 unpackbuf[i]=(drawing==1)?c1:c2;
1999 }
2000 }
2001 }
2002
2003 pack_tile(newtilebuf, unpackbuf,tile);
2004 }
2005 }
2006 ret = true;
2007 }
2008 break;
2009
2010 case t_eyedropper:
2011 if(floating_sel)
2012 memcpy(unpackbuf, floatsel, 256);
2013 else unpack_tile(newtilebuf, tile, 0, false);
2014
2015 if(gui_mouse_b()&1)
2016 {
2017 c1=unpackbuf[((y<<4)+x)];
2018 }
2019
2020 if(gui_mouse_b()&2)
2021 {
2022 c2=unpackbuf[((y<<4)+x)];
2023 }
2024 break;
2025
2026 case t_move:
2027 if((prev_x!=x)||(prev_y!=y))
2028 {
2029 if(has_selection())
2030 {
2031 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2032 wrap_sel_tile(y-prev_y, x-prev_x);
2033 shift_selection_grid(x-prev_x, y-prev_y);
2034 }
2035 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2036 prev_x=x;
2037 prev_y=y;
2038 }
2039 break;
2040
2041 case t_select:
2042 unfloat_selection();
2043 if(flip&1) x=15-x;
2044
2045 if(flip&2) y=15-y;
2046
2047 if(selecting_x1==-1||selecting_y1==-1)
2048 {
2049 selecting_x1=x;
2050 selecting_y1=y;
2051 }
2052 else
2053 {
2054 selecting_x2=x;
2055 selecting_y2=y;
2056 }
2057 break;
2058
2059 case t_wand:
2060 unfloat_selection();
2061 if(flip&1) x=15-x;
2062
2063 if(flip&2) y=15-y;
2064
2065 switch(select_mode)
2066 {
2067 case 0:
2068 clear_selection_grid();
2069 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2070 break;
2071
2072 case 1:
2073 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2074 break;
2075
2076 case 2:
2077 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2078 break;
2079
2080 case 3:
2081 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2082 break;
2083 }
2084
2085 ret = true;
2086 break;
2087 }
2088 return ret;
2089 }
2090 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2091 {
2092 popup_zqdialog_start();
2093 FONT* oldfont = font;
2094 font = get_custom_font(CFONT_DLG);
2095 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2096 status_info.yscale = text_height(font);
2097 status_info.y = 308-(status_info.h*status_info.yscale);
2098 hover_info.yscale = status_info.yscale;
2099 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2100 go();
2101 undocount = tilesize(newtilebuf[tile].format);
2102 clear_selection_grid();
2103 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2104
2105 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2106 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2107
2108 PALETTE tpal;
2109 byte oldtile[256];
2110
2111 memset(&tpal, 0, sizeof(PALETTE));
2112 memset(oldtile, 0, 256);
2113
2114 for(int32_t i=0; i<undocount; i++)
2115 {
2116 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2117 }
2118 byte undoselgrid[16][16];
2119 for(auto x = 0; x < 16; ++x)
2120 for(auto y = 0; y < 16; ++y)
2121 undoselgrid[x][y] = selection_grid[x+1][y+1];
2122 for(auto q = 0; q < 256; ++q)
2123 {
2124 floatsel[q] = 0;
2125 undofloatsel[q] = 0;
2126 floating_sel = false;
2127 undo_is_floatsel = false;
2128 }
2129
2130 int32_t tile_x=-1, tile_y=-1;
2131 int32_t temp_x=-1, temp_y=-1;
2132 bool bdown=false;
2133 int32_t done=0;
2134 drawing=0;
2135 tool_cur = -1;
2136
2137 get_palette(tpal);
2138
2139 if(newtilebuf[tile].format==tf4Bit)
2140 {
2141 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2142 }
2143 else
2144 {
2145 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2146 }
2147
2148 custom_vsync();
2149 zc_set_palette(tpal);
2150 draw_edit_scr(tile,flip,cs,oldtile, true);
2151
2152 while(gui_mouse_b())
2153 {
2154 /* do nothing */
2155 rest(1);
2156 }
2157
2158 move_origin_x=-1;
2159 move_origin_y=-1;
2160 prev_x=-1;
2161 prev_y=-1;
2162
2163
2164
2165 byte selection_pattern_source[8][8]=
2166 {
2167 {1, 1, 1, 1, 0, 0, 0, 0},
2168 {1, 1, 1, 0, 0, 0, 0, 1},
2169 {1, 1, 0, 0, 0, 0, 1, 1},
2170 {1, 0, 0, 0, 0, 1, 1, 1},
2171 {0, 0, 0, 0, 1, 1, 1, 1},
2172 {0, 0, 0, 1, 1, 1, 1, 0},
2173 {0, 0, 1, 1, 1, 1, 0, 0},
2174 {0, 1, 1, 1, 1, 0, 0, 0},
2175 };
2176
2177 byte selecting_pattern_source[8][8]=
2178 {
2179 {1, 1, 0, 0, 0, 0, 1, 1},
2180 {1, 0, 0, 0, 0, 1, 1, 1},
2181 {0, 0, 0, 0, 1, 1, 1, 1},
2182 {0, 0, 0, 1, 1, 1, 1, 0},
2183 {0, 0, 1, 1, 1, 1, 0, 0},
2184 {0, 1, 1, 1, 1, 0, 0, 0},
2185 {1, 1, 1, 1, 0, 0, 0, 0},
2186 {1, 1, 1, 0, 0, 0, 0, 1},
2187 };
2188
2189 byte intersection_pattern_source[8][8]=
2190 {
2191 {0, 0, 1, 1, 0, 0, 1, 1},
2192 {0, 1, 1, 0, 0, 1, 1, 0},
2193 {1, 1, 0, 0, 1, 1, 0, 0},
2194 {1, 0, 0, 1, 1, 0, 0, 1},
2195 {0, 0, 1, 1, 0, 0, 1, 1},
2196 {0, 1, 1, 0, 0, 1, 1, 0},
2197 {1, 1, 0, 0, 1, 1, 0, 0},
2198 {1, 0, 0, 1, 1, 0, 0, 1},
2199 };
2200
2201 selection_pattern=create_bitmap_ex(8, 8, 8);
2202
2203 for(int32_t x=0; x<8; ++x)
2204 {
2205 for(int32_t y=0; y<8; ++y)
2206 {
2207 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2208 }
2209 }
2210
2211 selecting_pattern=create_bitmap_ex(8, 8, 8);
2212
2213 for(int32_t x=0; x<8; ++x)
2214 {
2215 for(int32_t y=0; y<8; ++y)
2216 {
2217 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2218 }
2219 }
2220
2221 intersection_pattern=create_bitmap_ex(8, 8, 8);
2222
2223 for(int32_t x=0; x<8; ++x)
2224 {
2225 for(int32_t y=0; y<8; ++y)
2226 {
2227 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2228 }
2229 }
2230
2231 do
2232 {
2233 HANDLE_CLOSE_ZQDLG();
2234 if(exiting_program) break;
2235 int32_t temp_mouse_x=gui_mouse_x();
2236 int32_t temp_mouse_y=gui_mouse_y();
2237 rest(4);
2238 bool redraw=false;
2239 bool did_wand_select=false;
2240
2241 if(keypressed())
2242 {
2243 bool ctrl = CHECK_CTRL_CMD;
2244 int k = readkey()>>8;
2245 switch(k)
2246 {
2247 case KEY_F1:
2248 show_edit_tile_help();
2249 break;
2250 case KEY_ENTER_PAD:
2251 case KEY_ENTER:
2252 if(floating_sel)
2253 unfloat_selection();
2254 else done=2;
2255 break;
2256
2257 case KEY_ESC:
2258 if(floating_sel)
2259 unfloat_selection();
2260 else if(has_selection())
2261 clear_selection_grid();
2262 else done=1;
2263 break;
2264
2265 case KEY_DEL:
2266 {
2267 unpack_tile(newtilebuf, tile, 0, false);
2268 bool all = CHECK_CTRL_CMD || !has_selection();
2269 bool canDel = false;
2270 if(all)
2271 {
2272 //Check all
2273 for(auto q = 0; q < 256; ++q)
2274 if(unpackbuf[q])
2275 {
2276 canDel = true;
2277 break;
2278 }
2279 }
2280 else
2281 {
2282 //Check selection
2283 for(auto x = 0; x < 16; ++x)
2284 for(auto y = 0; y < 16; ++y)
2285 if(is_in_selection(x,y))
2286 if(unpackbuf[(y<<4)+x])
2287 {
2288 canDel = true;
2289 break;
2290 }
2291 }
2292 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2293
2294 for(int32_t i=0; i<undocount; i++)
2295 {
2296 undotile[i]=newtilebuf[tile].data[i];
2297 }
2298 for(auto x = 0; x < 16; ++x)
2299 for(auto y = 0; y < 16; ++y)
2300 undoselgrid[x][y] = selection_grid[x+1][y+1];
2301 for(auto q = 0; q < 256; ++q)
2302 undofloatsel[q] = floatsel[q];
2303 undo_is_floatsel = floating_sel;
2304
2305 if(CHECK_CTRL_CMD || !has_selection())
2306 {
2307 //Delete all
2308 for(auto q = 0; q < 256; ++q)
2309 {
2310 unpackbuf[q] = 0;
2311 floatsel[q] = 0;
2312 }
2313 }
2314 else
2315 {
2316 //Delete selection
2317 for(auto x = 0; x < 16; ++x)
2318 for(auto y = 0; y < 16; ++y)
2319 {
2320 if(floating_sel)
2321 {
2322 floatsel[x+(y<<4)] = 0;
2323 }
2324 else if(is_in_selection(x,y))
2325 {
2326 unpackbuf[(y<<4)+x] = 0;
2327 }
2328 }
2329 }
2330 pack_tile(newtilebuf, unpackbuf, tile);
2331 redraw=true;
2332 }
2333 break;
2334
2335 case KEY_A:
2336 clear_selection_grid();
2337 invert_selection_grid();
2338 redraw=true;
2339 break;
2340
2341 case KEY_D:
2342 clear_selection_grid();
2343 redraw=true;
2344 break;
2345
2346 case KEY_I:
2347 invert_selection_grid();
2348 redraw=true;
2349 break;
2350
2351 case KEY_H:
2352 flip^=1;
2353 normalize(tile,tile,0,flip);
2354 flip=0;
2355 redraw=true;
2356 break;
2357
2358 case KEY_V:
2359 flip^=2;
2360 normalize(tile,tile,0,flip);
2361 flip=0;
2362 redraw=true;
2363 break;
2364
2365 case KEY_F12:
2366 onSnapshot();
2367 break;
2368
2369 case KEY_R:
2370 {
2371 //if(CHECK_CTRL_CMD))
2372 // {
2373 //do_recolor(tile); redraw=true; saved=false;
2374 // }
2375 //else
2376 // {
2377 go_tiles();
2378 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2379 redraw=true;
2380 saved=false;
2381 break;
2382 }
2383
2384 case KEY_EQUALS:
2385 case KEY_PLUS_PAD:
2386 {
2387 if(CHECK_CTRL_CMD ||
2388 key[KEY_ALT] || key[KEY_ALTGR])
2389 {
2390 for(int32_t i=0; i<undocount; i++)
2391 undotile[i]=newtilebuf[tile].data[i];
2392 for(auto x = 0; x < 16; ++x)
2393 for(auto y = 0; y < 16; ++y)
2394 undoselgrid[x][y] = selection_grid[x+1][y+1];
2395 for(auto q = 0; q < 256; ++q)
2396 undofloatsel[q] = floatsel[q];
2397 undo_is_floatsel = floating_sel;
2398
2399 if(key[KEY_ALT] || key[KEY_ALTGR])
2400 shift_tile_colors(tile, 16, false);
2401 else
2402 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2403 }
2404 else
2405 cs = (cs<13) ? cs+1:0;
2406
2407 redraw=true;
2408 break;
2409 }
2410
2411 case KEY_MINUS:
2412 case KEY_MINUS_PAD:
2413 {
2414 if(CHECK_CTRL_CMD ||
2415 key[KEY_ALT] || key[KEY_ALTGR])
2416 {
2417 for(int32_t i=0; i<undocount; i++)
2418 undotile[i]=newtilebuf[tile].data[i];
2419 for(auto x = 0; x < 16; ++x)
2420 for(auto y = 0; y < 16; ++y)
2421 undoselgrid[x][y] = selection_grid[x+1][y+1];
2422 for(auto q = 0; q < 256; ++q)
2423 undofloatsel[q] = floatsel[q];
2424 undo_is_floatsel = floating_sel;
2425
2426 if(key[KEY_ALT] || key[KEY_ALTGR])
2427 shift_tile_colors(tile, -16, false);
2428 else
2429 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2430 }
2431 else
2432 cs = (cs>0) ? cs-1:13;
2433
2434 redraw=true;
2435 break;
2436 }
2437
2438 case KEY_SPACE:
2439 gridmode=(gridmode+1)%gm_max;
2440 redraw=true;
2441 break;
2442
2443 case KEY_Z:
2444 if(!ctrl)
2445 break;
2446 //Ctrl+Z == undo
2447 [[fallthrough]];
2448 case KEY_U:
2449 for(int32_t i=0; i<undocount; i++)
2450 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2451
2452 for(auto x = 0; x < 16; ++x)
2453 for(auto y = 0; y < 16; ++y)
2454 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2455
2456 for(auto q = 0; q < 256; ++q)
2457 zc_swap(undofloatsel[q], floatsel[q]);
2458 zc_swap(undo_is_floatsel, floating_sel);
2459
2460 redraw=true;
2461 break;
2462
2463 case KEY_S:
2464 if(CHECK_CTRL_CMD)
2465 {
2466 for(int32_t i=0; i<undocount; i++)
2467 {
2468 undotile[i]=newtilebuf[tile].data[i];
2469 }
2470 for(auto x = 0; x < 16; ++x)
2471 for(auto y = 0; y < 16; ++y)
2472 undoselgrid[x][y] = selection_grid[x+1][y+1];
2473 for(auto q = 0; q < 256; ++q)
2474 undofloatsel[q] = floatsel[q];
2475 undo_is_floatsel = floating_sel;
2476
2477 unpack_tile(newtilebuf, tile, 0, false);
2478
2479 if(has_selection())
2480 {
2481 for(int32_t i=0; i<256; i++)
2482 {
2483 if(!is_in_selection(i%16,i/16))
2484 continue;
2485 if(unpackbuf[i]==c1)
2486 {
2487 unpackbuf[i]=c2;
2488 }
2489 else if(unpackbuf[i]==c2)
2490 {
2491 unpackbuf[i]=c1;
2492 }
2493 if(floating_sel)
2494 {
2495 if(floatsel[i]==c1)
2496 {
2497 floatsel[i]=c2;
2498 }
2499 else if(floatsel[i]==c2)
2500 {
2501 floatsel[i]=c1;
2502 }
2503 }
2504 }
2505 }
2506 else
2507 {
2508 for(int32_t i=0; i<256; i++)
2509 {
2510 if(unpackbuf[i]==c1)
2511 {
2512 unpackbuf[i]=c2;
2513 }
2514 else if(unpackbuf[i]==c2)
2515 {
2516 unpackbuf[i]=c1;
2517 }
2518 }
2519 }
2520
2521 pack_tile(newtilebuf, unpackbuf,tile);
2522 }
2523
2524 zc_swap(c1,c2);
2525 redraw=true;
2526 break;
2527
2528 case KEY_UP:
2529 if(CHECK_CTRL_CMD)
2530 {
2531 unfloat_selection();
2532 tile=zc_max(0,tile-TILES_PER_ROW);
2533 undocount = tilesize(newtilebuf[tile].format);
2534
2535 for(int32_t i=0; i<undocount; i++)
2536 {
2537 undotile[i]=newtilebuf[tile].data[i];
2538 oldtile[i]=undotile[i];
2539 }
2540
2541 redraw=true;
2542 }
2543 else
2544 {
2545 for(int32_t i=0; i<undocount; i++)
2546 {
2547 undotile[i]=newtilebuf[tile].data[i];
2548 }
2549 for(auto x = 0; x < 16; ++x)
2550 for(auto y = 0; y < 16; ++y)
2551 undoselgrid[x][y] = selection_grid[x+1][y+1];
2552 for(auto q = 0; q < 256; ++q)
2553 undofloatsel[q] = floatsel[q];
2554 undo_is_floatsel = floating_sel;
2555 if(has_selection())
2556 {
2557 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2558 wrap_sel_tile(-1, 0);
2559 shift_selection_grid(0, -1);
2560 }
2561 else wrap_tile(tile, -1, 0, false);
2562 redraw=true;
2563 }
2564 break;
2565
2566 case KEY_DOWN:
2567 if(CHECK_CTRL_CMD)
2568 {
2569 unfloat_selection();
2570 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2571 undocount = tilesize(newtilebuf[tile].format);
2572
2573 for(int32_t i=0; i<undocount; i++)
2574 {
2575 undotile[i]=newtilebuf[tile].data[i];
2576 oldtile[i]=undotile[i];
2577 }
2578
2579 redraw=true;
2580 }
2581 else
2582 {
2583 for(int32_t i=0; i<undocount; i++)
2584 {
2585 undotile[i]=newtilebuf[tile].data[i];
2586 }
2587 for(auto x = 0; x < 16; ++x)
2588 for(auto y = 0; y < 16; ++y)
2589 undoselgrid[x][y] = selection_grid[x+1][y+1];
2590 for(auto q = 0; q < 256; ++q)
2591 undofloatsel[q] = floatsel[q];
2592 undo_is_floatsel = floating_sel;
2593 if(has_selection())
2594 {
2595 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2596 wrap_sel_tile(1, 0);
2597 shift_selection_grid(0, 1);
2598 }
2599 else wrap_tile(tile, 1, 0, false);
2600 redraw=true;
2601 }
2602 break;
2603
2604 case KEY_LEFT:
2605 if(CHECK_CTRL_CMD)
2606 {
2607 unfloat_selection();
2608 tile=zc_max(0,tile-1);
2609 undocount = tilesize(newtilebuf[tile].format);
2610
2611 for(int32_t i=0; i<undocount; i++)
2612 {
2613 undotile[i]=newtilebuf[tile].data[i];
2614 oldtile[i]=undotile[i];
2615 }
2616
2617 redraw=true;
2618 }
2619 else
2620 {
2621 for(int32_t i=0; i<undocount; i++)
2622 {
2623 undotile[i]=newtilebuf[tile].data[i];
2624 }
2625 for(auto x = 0; x < 16; ++x)
2626 for(auto y = 0; y < 16; ++y)
2627 undoselgrid[x][y] = selection_grid[x+1][y+1];
2628 for(auto q = 0; q < 256; ++q)
2629 undofloatsel[q] = floatsel[q];
2630 undo_is_floatsel = floating_sel;
2631 if(has_selection())
2632 {
2633 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2634 wrap_sel_tile(0, -1);
2635 shift_selection_grid(-1, 0);
2636 }
2637 else wrap_tile(tile, 0, -1, false);
2638 redraw=true;
2639 }
2640 break;
2641
2642 case KEY_RIGHT:
2643 if(CHECK_CTRL_CMD)
2644 {
2645 unfloat_selection();
2646 tile=zc_min(tile+1, NEWMAXTILES-1);
2647 undocount = tilesize(newtilebuf[tile].format);
2648
2649 for(int32_t i=0; i<undocount; i++)
2650 {
2651 undotile[i]=newtilebuf[tile].data[i];
2652 oldtile[i]=undotile[i];
2653 }
2654
2655 redraw=true;
2656 }
2657 else
2658 {
2659 for(int32_t i=0; i<undocount; i++)
2660 {
2661 undotile[i]=newtilebuf[tile].data[i];
2662 }
2663 for(auto x = 0; x < 16; ++x)
2664 for(auto y = 0; y < 16; ++y)
2665 undoselgrid[x][y] = selection_grid[x+1][y+1];
2666 for(auto q = 0; q < 256; ++q)
2667 undofloatsel[q] = floatsel[q];
2668 undo_is_floatsel = floating_sel;
2669 if(has_selection())
2670 {
2671 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2672 wrap_sel_tile(0, 1);
2673 shift_selection_grid(1, 0);
2674 }
2675 else wrap_tile(tile, 0, 1, false);
2676 redraw=true;
2677 }
2678 break;
2679 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2680 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2681 case KEY_8: case KEY_9:
2682 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2683 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2684 case KEY_8_PAD: case KEY_9_PAD:
2685 {
2686 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2687 if(unsigned(t) < t_max)
2688 {
2689 if(old_tool != -1)
2690 old_tool = t;
2691 else tool = t;
2692 }
2693 break;
2694 }
2695 case KEY_TAB:
2696 {
2697 if(key_shifts & KB_CTRL_CMD_FLAG)
2698 {
2699 xmode = (xmode+1)%XMODE_MAX;
2700 if(!xmode)
2701 bgmode = (bgmode+1)%BGMODE_MAX;
2702 }
2703 else if(key_shifts & KB_SHIFT_FLAG)
2704 hide_grid = !hide_grid;
2705 else show_quartgrid = !show_quartgrid;
2706 redraw = true;
2707 break;
2708 }
2709 }
2710 clear_keybuf();
2711 }
2712
2713 if(!gui_mouse_b())
2714 {
2715 if(is_selecting())
2716 {
2717 unfloat_selection();
2718 int32_t x1=zc_min(selecting_x1,selecting_x2);
2719 int32_t x2=zc_max(selecting_x1,selecting_x2);
2720 int32_t y1=zc_min(selecting_y1,selecting_y2);
2721 int32_t y2=zc_max(selecting_y1,selecting_y2);
2722
2723 if(select_mode==0)
2724 {
2725 clear_selection_grid();
2726 }
2727
2728 for(int32_t x=x1; x<=x2; ++x)
2729 {
2730 for(int32_t y=y1; y<=y2; ++y)
2731 {
2732 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2733 }
2734 }
2735
2736 if(select_mode==3)
2737 {
2738 for(int32_t y=0; y<16; ++y)
2739 {
2740 for(int32_t x=0; x<x1; ++x)
2741 {
2742 selection_grid[x+1][y+1]=0;
2743 }
2744
2745 for(int32_t x=x2+1; x<16; ++x)
2746 {
2747 selection_grid[x+1][y+1]=0;
2748 }
2749 }
2750
2751 for(int32_t x=x1; x<=x2; ++x)
2752 {
2753 for(int32_t y=0; y<y1; ++y)
2754 {
2755 selection_grid[x+1][y+1]=0;
2756 }
2757
2758 for(int32_t y=y2+1; y<16; ++y)
2759 {
2760 selection_grid[x+1][y+1]=0;
2761 }
2762 }
2763 }
2764 }
2765
2766 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2767 did_wand_select=false;
2768 }
2769
2770 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2771 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2772 bool ctrl=CHECK_CTRL_CMD;
2773 static int32_t last_tool_val = 0;
2774
2775 if(tool==t_select||tool==t_wand)
2776 {
2777 if(!drawing)
2778 {
2779 int32_t type=0;
2780
2781 if(has_selection())
2782 {
2783 if(shift)
2784 {
2785 type+=1;
2786 }
2787
2788 if(alt)
2789 {
2790 type+=2;
2791 }
2792 }
2793
2794 if(type!=select_mode)
2795 {
2796 select_mode=type;
2797
2798 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2799 set_tool_sprite(tool,type);
2800 }
2801 }
2802 }
2803 else if(alt||ctrl)
2804 {
2805 if(old_tool==-1)
2806 {
2807 old_tool = tool;
2808 tool_cur = -1;
2809 }
2810 if(alt&&ctrl)
2811 tool = t_recolor;
2812 else if(alt)
2813 tool = t_eyedropper;
2814 else tool = t_fill;
2815 }
2816 else if(old_tool!=-1)
2817 {
2818 tool = old_tool;
2819 old_tool = -1;
2820 tool_cur = -1;
2821 redraw = true;
2822 }
2823 if(last_tool_val != tool)
2824 {
2825 redraw = true;
2826 tool_cur = -1;
2827 update_tool_cursor();
2828 last_tool_val = tool;
2829 }
2830
2831 if(!bdown)
2832 {
2833 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2834 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2835 }
2836
2837 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2838 {
2839 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2840 {
2841 if(tool==t_move || tool==t_fill)
2842 {
2843 set_tool_sprite(tool,1);
2844
2845 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2846 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2847 }
2848
2849 for(int32_t i=0; i<undocount; i++)
2850 {
2851 undotile[i]=newtilebuf[tile].data[i];
2852 }
2853 for(auto x = 0; x < 16; ++x)
2854 for(auto y = 0; y < 16; ++y)
2855 undoselgrid[x][y] = selection_grid[x+1][y+1];
2856 for(auto q = 0; q < 256; ++q)
2857 undofloatsel[q] = floatsel[q];
2858 undo_is_floatsel = floating_sel;
2859
2860 drawing=1;
2861 }
2862
2863 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2864 {
2865 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2866 {
2867 done=2;
2868 }
2869 }
2870
2871 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2872 {
2873 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2874 {
2875 done=1;
2876 }
2877 }
2878
2879 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2880 {
2881 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2882 {
2883 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2884 get_palette(tpal);
2885
2886 if(newtilebuf[tile].format==tf4Bit)
2887 {
2888 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2889 }
2890 else
2891 {
2892 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2893 }
2894
2895 redraw=true;
2896 }
2897 }
2898
2899 int sqr_clicked;
2900 if(show_quartgrid && qgrid_tool(tool))
2901 {
2902 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2903 if(sqr_clicked > -1)
2904 {
2905 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2906 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2907 refl_flags ^= (1<<sqr_clicked);
2908 }
2909 }
2910 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2911 if(sqr_clicked > -1)
2912 {
2913 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2914 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2915 xmode = sqr_clicked;
2916 }
2917 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2918 if(sqr_clicked > -1)
2919 {
2920 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2921 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2922 bgmode = sqr_clicked;
2923 }
2924
2925 if(showcolortip)
2926 {
2927 auto oy = color_info.y;
2928 if(reftile <= 0)
2929 color_info.y -= ref_til.h + 8;
2930 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2931 {
2932 showcolortip = 0;
2933 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2934 }
2935 color_info.y = oy;
2936 }
2937 else
2938 {
2939 auto oy = color_info_btn.y;
2940 if(reftile <= 0)
2941 color_info_btn.y -= ref_til.h + 8;
2942 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2943 {
2944 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2945 {
2946 showcolortip = 1;
2947 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2948 redraw=true;
2949 }
2950 }
2951 color_info_btn.y = oy;
2952 }
2953
2954 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2955 {
2956 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2957 {
2958 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2959 redraw=true;
2960 }
2961 }
2962 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2963 {
2964 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2965 redraw=true;
2966 }
2967 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2968 {
2969 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2970 redraw=true;
2971 }
2972
2973 switch(newtilebuf[tile].format)
2974 {
2975 case tf4Bit:
2976 {
2977 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2978 if(ind > -1)
2979 {
2980 c1 = ind;
2981 redraw=true;
2982 }
2983 break;
2984 }
2985 case tf8Bit:
2986 {
2987 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2988 if(ind > -1)
2989 {
2990 c1 = ind;
2991 redraw=true;
2992 }
2993 break;
2994 }
2995 }
2996
2997
2998 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2999 if(newtool > -1 && newtool < t_max)
3000 {
3001 tool=newtool;
3002 redraw=true;
3003 }
3004
3005 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
3006 {
3007 if(do_x_button(screen, x_btn.x, x_btn.y))
3008 {
3009 done=1;
3010 }
3011 }
3012 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
3013 {
3014 if(do_question_button(screen, info_btn.x, info_btn.y))
3015 {
3016 show_edit_tile_help();
3017 }
3018 }
3019
3020 bdown=true;
3021 }
3022
3023 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3024 {
3025 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3026 {
3027 if(tool==t_move || tool==t_fill)
3028 {
3029 set_tool_sprite(tool,1);
3030
3031 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3032 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3033 }
3034
3035 for(int32_t i=0; i<undocount; i++)
3036 {
3037 undotile[i]=newtilebuf[tile].data[i];
3038 }
3039 for(auto x = 0; x < 16; ++x)
3040 for(auto y = 0; y < 16; ++y)
3041 undoselgrid[x][y] = selection_grid[x+1][y+1];
3042 for(auto q = 0; q < 256; ++q)
3043 undofloatsel[q] = floatsel[q];
3044 undo_is_floatsel = floating_sel;
3045
3046 drawing=2;
3047 }
3048
3049 switch(newtilebuf[tile].format)
3050 {
3051 case tf4Bit:
3052 {
3053 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3054 if(ind > -1)
3055 {
3056 c2 = ind;
3057 redraw=true;
3058 }
3059 break;
3060 }
3061 case tf8Bit:
3062 {
3063 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3064 if(ind > -1)
3065 {
3066 c2 = ind;
3067 redraw=true;
3068 }
3069 break;
3070 }
3071 }
3072
3073 bdown=true;
3074 }
3075
3076 if(bdown&&!gui_mouse_b()) //released the buttons
3077 {
3078 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3079 {
3080 if(tool==t_move || tool==t_fill)
3081 {
3082 set_tool_sprite(tool,0);
3083 }
3084 }
3085 }
3086
3087 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3088 {
3089 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3090 int32_t x=ind%zoomtile.w;
3091 int32_t y=ind/zoomtile.w;
3092
3093 bool reset_draw = false;
3094
3095 if(__pixel_draw(x,y,tile,flip))
3096 reset_draw = true;
3097 if(show_quartgrid)
3098 {
3099 auto tmp_sel_mode = select_mode;
3100 if(tool == t_wand && select_mode == 0)
3101 select_mode = 1;
3102 if(qgrid_tool(tool))
3103 {
3104 if(refl_flags & (1<<REFL_HFLIP))
3105 if(__pixel_draw(15-x,y,tile,flip))
3106 reset_draw = true;
3107 if(refl_flags & (1<<REFL_VFLIP))
3108 if(__pixel_draw(x,15-y,tile,flip))
3109 reset_draw = true;
3110 //Diagonal flip and 180° rotation are the same!
3111 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3112 if(__pixel_draw(15-x,15-y,tile,flip))
3113 reset_draw = true;
3114 if(refl_flags & (1<<REFL_90CW))
3115 if(__pixel_draw(15-y,x,tile,flip))
3116 reset_draw = true;
3117 if(refl_flags & (1<<REFL_90CCW))
3118 if(__pixel_draw(y,15-x,tile,flip))
3119 reset_draw = true;
3120 }
3121 select_mode = tmp_sel_mode;
3122 }
3123
3124 if(reset_draw)
3125 drawing = 0;
3126 redraw=true;
3127 }
3128
3129 if(gui_mouse_b()==0)
3130 {
3131 bdown=false;
3132 drawing=0;
3133 }
3134
3135 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3136 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3137
3138 {
3139 tile_x=temp_x;
3140 tile_y=temp_y;
3141 redraw=true;
3142 }
3143
3144 const char *toolnames[t_max]=
3145 {
3146 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3147 };
3148
3149 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3150 if(toolbtn > -1 && toolbtn < t_max)
3151 {
3152 int32_t column = toolbtn%tool_btns.w;
3153 int32_t row = toolbtn/tool_btns.w;
3154
3155 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3156 redraw=true;
3157 }
3158 /* Highlight the hovered pixel? Eh, maybe too much?
3159 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3160 if(hov_pix > -1)
3161 {
3162 int32_t column = hov_pix%zoomtile.w;
3163 int32_t row = hov_pix/zoomtile.w;
3164
3165 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3166 redraw=true;
3167 }*/
3168
3169 if(redraw)
3170 {
3171 custom_vsync();
3172 draw_edit_scr(tile,flip,cs,oldtile, false);
3173 }
3174 else
3175 {
3176 bool hs=has_selection();
3177
3178 if(hs)
3179 {
3180 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3181 }
3182
3183 custom_vsync();
3184
3185 if(hs)
3186 {
3187 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3188 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3189 }
3190
3191 update_tool_cursor();
3192 SCRFIX();
3193 }
3194
3195 }
3196 while(!done);
3197
3198 unfloat_selection();
3199 clear_selection_grid();
3200
3201 while(gui_mouse_b())
3202 {
3203 /* do nothing */
3204 rest(1);
3205 }
3206
3207 if(done==1)
3208 {
3209 for(int32_t i=0; i<undocount; i++)
3210 {
3211 newtilebuf[tile].data[i]=oldtile[i];
3212 }
3213 }
3214 else
3215 {
3216 byte *buf = new byte[undocount];
3217
3218 // put back old tile
3219 for(int32_t i=0; i<undocount; i++)
3220 {
3221 buf[i] = newtilebuf[tile].data[i];
3222 newtilebuf[tile].data[i] = oldtile[i];
3223 }
3224
3225 // go
3226 go_tiles();
3227
3228 // replace old tile with new one again
3229 for(int32_t i=0; i<undocount; i++)
3230 {
3231 newtilebuf[tile].data[i] = buf[i];
3232 }
3233
3234 saved=false;
3235
3236 if(buf!=NULL)
3237 {
3238 delete[] buf;
3239 }
3240 }
3241
3242 MouseSprite::set(ZQM_NORMAL);
3243 register_blank_tiles();
3244 register_used_tiles();
3245 clear_tooltip();
3246 comeback();
3247 destroy_bitmap(selection_pattern);
3248 destroy_bitmap(selecting_pattern);
3249 destroy_bitmap(intersection_pattern);
3250 font = oldfont;
3251 popup_zqdialog_end();
3252 }
3253
3254 /* Grab Tile Code */
3255
3256 enum recolorState { rcNone, rc4Bit, rc8Bit };
3257
3258 BITMAP* original_imagebuf_bitmap=NULL;
3259 void *imagebuf=NULL;
3260 int32_t imagebuf_bitmap_scale=0;
3261 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3262 int32_t imagesize=0;
3263 int32_t tilecount=0;
3264 int32_t imagetype=0;
3265 int32_t imagex,imagey,selx,sely;
3266 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3267 bool nesmode=false;
3268 int32_t grabmask=0;
3269 recolorState recolor=rcNone;
3270 PALETTE imagepal;
3271
3272 /* bestfit_color:
3273 * Searches a palette for the color closest to the requested R, G, B value.
3274 */
3275 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3276 {
3277 int32_t bestMatch = 0; // Color with the lowest total difference so far
3278 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3279 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3280
3281 for(int32_t i = 0; i < CSET_SIZE; i++)
3282 {
3283 byte *rgbByte;
3284
3285 // This seems to be right...
3286 if(cs==2 || cs==3 || cs==4)
3287 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3288 else if(cs==9)
3289 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3290 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3291 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3292 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3293 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3294 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3295 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3296 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3297 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3298 else
3299 rgbByte = colordata + (CSET(cs)+i)*3;
3300
3301 int32_t dr=r-*rgbByte;
3302 int32_t dg=g-*(rgbByte+1);
3303 int32_t db=b-*(rgbByte+2);
3304
3305 // Track both the total color difference and the single greatest
3306 // difference of R, G, B. The idea is that it's better to have
3307 // two or three small differences than one big one.
3308 // The differences are multiplied by different numbers to account
3309 // for the differences in perceived brightness of the three colors.
3310 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3311 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3312
3313 // Perfect match? Just stop here.
3314 if(totalDiff==0)
3315 return i;
3316
3317 if(totalDiff < bestTotalDiff || // Best match so far?
3318 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3319 {
3320 bestMatch=i;
3321 bestTotalDiff=totalDiff;
3322 bestHighDiff=highDiff;
3323 }
3324 }
3325
3326 return bestMatch;
3327 }
3328
3329 // Same as the above, but draws from all colors in CSets 0-11.
3330 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3331 {
3332 int32_t bestMatch = 0;
3333 float bestTotalDiff = 100000;
3334 float bestHighDiff = 100000;
3335
3336 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3337 {
3338 byte *rgbByte;
3339
3340 int32_t cs=i>>4;
3341 if(cs==2 || cs==3 || cs==4)
3342 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3343 else if(cs==9)
3344 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3345 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3346 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3347 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3348 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3349 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3350 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3351 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3352 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3353 else
3354 rgbByte = colordata + i * 3;
3355
3356 int32_t dr=r-*rgbByte;
3357 int32_t dg=g-*(rgbByte+1);
3358 int32_t db=b-*(rgbByte+2);
3359
3360 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3361 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3362
3363 if(totalDiff==0) // Perfect match?
3364 return i;
3365
3366 if(totalDiff < bestTotalDiff || // Best match so far?
3367 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3368 {
3369 bestMatch=i;
3370 bestTotalDiff=totalDiff;
3371 bestHighDiff=highDiff;
3372 }
3373 }
3374
3375 return bestMatch;
3376 }
3377
3378 byte cset_reduce_table[PAL_SIZE];
3379
3380 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3381 {
3382 for(int32_t i=0; i<PAL_SIZE; i++)
3383 {
3384 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3385 }
3386 }
3387
3388 void calc_cset_reduce_table_8bit(PALETTE pal)
3389 {
3390 for(int32_t i=0; i<PAL_SIZE; i++)
3391 {
3392 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3393 }
3394 }
3395
3396 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3397 {
3398 //storage space for the grabbed image
3399 byte buf[64];
3400 memset(buf,0,64);
3401 byte *oldsrc=src;
3402
3403 //for 8 lines in the source image...
3404 for(int32_t line=0; line<(nesmode?4:8); line++)
3405 {
3406 //bx is the pixel at the start of a line in the storage buffer
3407 int32_t bx=line<<(nesmode?4:3);
3408 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3409 byte b=src[(bp&1)?line:line<<1];
3410
3411 //fill the storage buffer with data from the source image
3412 for(int32_t i=7; i>=0; --i)
3413 {
3414 buf[bx+i] = (b&1)+(cs<<4);
3415 b>>=1;
3416 }
3417 }
3418
3419 ++src;
3420
3421 for(int32_t p=1; p<bp; p++)
3422 {
3423 for(int32_t line=0; line<(nesmode?4:8); line++)
3424 {
3425 int32_t bx=line<<(nesmode?4:3);
3426 byte b=src[(bp&1)?line:line<<1];
3427
3428 for(int32_t i=7; i>=0; --i)
3429 {
3430 if(nesmode)
3431 {
3432 buf[bx+8+i] = (b&1)+(cs<<4);
3433 }
3434 else
3435 {
3436 buf[bx+i] |= (b&1)<<p;
3437 }
3438
3439 b>>=1;
3440 }
3441 }
3442
3443 if(p&1)
3444 {
3445 src+=15;
3446 }
3447 else
3448 {
3449 ++src;
3450 }
3451 }
3452
3453
3454 if(nesmode)
3455 {
3456 src=oldsrc;
3457
3458 for(int32_t counter=0; counter<2; ++counter, ++src)
3459 {
3460 //for 8 lines in the source image...
3461 for(int32_t line=0; line<4; line++)
3462 {
3463 //bx is the pixel at the start of a line in the storage buffer
3464 int32_t bx=line<<4;
3465 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3466 byte b=src[(line+4)<<1];
3467
3468 //fill the storage buffer with data from the source image
3469 for(int32_t i=7; i>=0; --i)
3470 {
3471 // buf[bx+i] = (b&1)+(cs<<4);
3472 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3473 b>>=1;
3474 }
3475 }
3476 }
3477 }
3478
3479 int32_t c=0;
3480
3481 switch(romtilemode)
3482 {
3483 case 0:
3484 case 1:
3485 case 2:
3486 for(int32_t j=0; j<8; j++)
3487 {
3488 for(int32_t i=0; i<8; i++)
3489 {
3490 putpixel(dest,x+i,y+j,buf[c++]);
3491 }
3492 }
3493
3494 break;
3495
3496 case 3:
3497 for(int32_t j=0; j<4; j++)
3498 {
3499 for(int32_t i=0; i<16; i++)
3500 {
3501 putpixel(dest,x+i,y+j,buf[c++]);
3502 }
3503 }
3504
3505 break;
3506 }
3507 }
3508
3509 const char *file_type[ftMAX]=
3510 {
3511 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3512 };
3513
3514 void draw_grab_window()
3515 {
3516 int w = 640;
3517 int h = 480;
3518 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3519 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3520 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3521 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3522
3523 FONT *oldfont = font;
3524 font = get_zc_font(font_lfont);
3525 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3526 font=oldfont;
3527 }
3528
3529 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3530 {
3531 width=width;
3532 height=height;
3533 white=white; // happy birthday compiler
3534
3535 int32_t yofs=0;
3536 //clear_to_color(screen2,bg);
3537 rectfill(screen2, 0, 0, 319, 159, black);
3538 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3539 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3540 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3541 yofs=3;
3542
3543 // text_mode(-1);
3544 int32_t tileromcolumns=20;
3545
3546 switch(imagetype)
3547 {
3548 case ftBMP:
3549 if(recolor==rcNone)
3550 {
3551 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3552 }
3553 else
3554 {
3555 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3556 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3557
3558 for(int32_t y=0; y<maxy; y++)
3559 {
3560 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3561 {
3562 break;
3563 }
3564
3565 for(int32_t x=0; x<maxx; x++)
3566 {
3567 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3568 {
3569 break;
3570 }
3571
3572 if(recolor==rc8Bit)
3573 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3574 else
3575 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3576 }
3577 }
3578 }
3579
3580 break;
3581
3582 case ftZGP:
3583 case ftQST:
3584 case ftZQT:
3585 case ftQSU:
3586 case ftTIL:
3587 {
3588 tiledata *hold = newtilebuf;
3589 newtilebuf = grabtilebuf;
3590 //fixme
3591 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3592 int32_t t=imagey*TILES_PER_ROW;
3593
3594 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3595 {
3596 if(t <= tilecount)
3597 {
3598 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3599 }
3600
3601 ++t;
3602 }
3603
3604 newtilebuf = hold;
3605 //fixme
3606 }
3607 break;
3608
3609 case ftBIN:
3610 {
3611 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3612 byte *buf = (byte*)imagebuf;
3613
3614 switch(romtilemode)
3615 {
3616 case 0:
3617 for(int32_t y=0; y<160; y+=8)
3618 {
3619 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3620 {
3621 puttileROM(screen2,x,y,buf+ofs,cs);
3622 ofs+=8*bp;
3623 }
3624 }
3625
3626 for(int32_t y=0; y<160; y+=8)
3627 {
3628 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3629 {
3630 puttileROM(screen2,x+128,y,buf+ofs,cs);
3631 ofs+=8*bp;
3632 }
3633 }
3634
3635 break;
3636
3637 case 1:
3638 for(int32_t y=0; y<160; y+=16)
3639 {
3640 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3641 {
3642 puttileROM(screen2,x,y,buf+ofs,cs);
3643 ofs+=8*bp;
3644 puttileROM(screen2,x,y+8,buf+ofs,cs);
3645 ofs+=8*bp;
3646 }
3647 }
3648
3649 for(int32_t y=0; y<160; y+=16)
3650 {
3651 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3652 {
3653 puttileROM(screen2,x+128,y,buf+ofs,cs);
3654 ofs+=8*bp;
3655 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3656 ofs+=8*bp;
3657 }
3658 }
3659
3660 break;
3661
3662 case 2:
3663 for(int32_t y=0; y<160; y+=16)
3664 {
3665 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3666 {
3667 puttileROM(screen2,x,y,buf+ofs,cs);
3668 ofs+=8*bp;
3669 puttileROM(screen2,x+8,y,buf+ofs,cs);
3670 ofs+=8*bp;
3671 puttileROM(screen2,x,y+8,buf+ofs,cs);
3672 ofs+=8*bp;
3673 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3674 ofs+=8*bp;
3675 }
3676 }
3677
3678 for(int32_t y=0; y<160; y+=16)
3679 {
3680 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3681 {
3682 puttileROM(screen2,x+128,y,buf+ofs,cs);
3683 ofs+=8*bp;
3684 puttileROM(screen2,x+136,y,buf+ofs,cs);
3685 ofs+=8*bp;
3686 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3687 ofs+=8*bp;
3688 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3689 ofs+=8*bp;
3690 }
3691 }
3692
3693 break;
3694
3695 case 3:
3696 for(int32_t y=0; y<160; y+=16)
3697 {
3698 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3699 {
3700 puttileROM(screen2,x,y,buf+ofs,cs);
3701 ofs+=8*bp;
3702 puttileROM(screen2,x,y+4,buf+ofs,cs);
3703 ofs+=8*bp;
3704 puttileROM(screen2,x,y+8,buf+ofs,cs);
3705 ofs+=8*bp;
3706 puttileROM(screen2,x,y+12,buf+ofs,cs);
3707 ofs+=8*bp;
3708 }
3709 }
3710
3711 for(int32_t y=0; y<160; y+=16)
3712 {
3713 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3714 {
3715 puttileROM(screen2,x+128,y,buf+ofs,cs);
3716 ofs+=8*bp;
3717 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3718 ofs+=8*bp;
3719 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3720 ofs+=8*bp;
3721 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3722 ofs+=8*bp;
3723 }
3724 }
3725
3726 break;
3727 }
3728 }
3729 break;
3730 }
3731
3732 tiledata hold;
3733 bool holdblank = blank_tile_table[0];
3734
3735 if(is_valid_format(newtilebuf[0].format))
3736 {
3737 hold.format = newtilebuf[0].format;
3738 hold.data = (byte *)malloc(tilesize(hold.format));
3739 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3740 }
3741 else
3742 {
3743 hold.format=tfInvalid;
3744 hold.data=NULL;
3745 }
3746
3747 newtilebuf[0].format=newformat[0];
3748 blank_tile_table[0] = false;
3749
3750 if(newtilebuf[0].data!=NULL)
3751 {
3752 free(newtilebuf[0].data);
3753 }
3754
3755 if(is_valid_format(newtilebuf[0].format))
3756 {
3757 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3758
3759 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3760 {
3761 newtilebuf[0].data[i]=newtile[i];
3762 }
3763 }
3764 else
3765 {
3766 newtilebuf[0].data=NULL;
3767 }
3768
3769 puttile16(screen2,0,208,168+yofs,cs,0);
3770 overtile16(screen2,0,232,168+yofs,cs,0);
3771 newtilebuf[0].format=hold.format;
3772 blank_tile_table[0] = holdblank;
3773
3774 if(newtilebuf[0].data!=NULL)
3775 {
3776 free(newtilebuf[0].data);
3777 }
3778
3779 if(is_valid_format(newtilebuf[0].format))
3780 {
3781 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3782
3783 for(int32_t i=0; i<256; i++)
3784 {
3785 newtilebuf[0].data[i]=hold.data[i];
3786 }
3787 }
3788 else
3789 {
3790 newtilebuf[0].data=NULL;
3791 }
3792
3793 if(hold.data!=NULL)
3794 {
3795 free(hold.data);
3796 }
3797
3798 puttile16(screen2,tile,208,192+yofs,cs,0);
3799 overtile16(screen2,tile,232,192+yofs,cs,0);
3800
3801 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3802 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3803 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3804 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3805
3806 // rect(screen2,183,167,200,184,dvc(7*2));
3807 // rect(screen2,207,167,224,184,dvc(7*2));
3808 // rect(screen2,231,167,248,184,dvc(7*2));
3809 // rect(screen2,207,191,224,208,dvc(7*2));
3810 // rect(screen2,231,191,248,208,dvc(7*2));
3811
3812 /*
3813 rect(screen2,183,167,200,184,vc(14));
3814 rect(screen2,207,167,224,184,vc(14));
3815 rect(screen2,231,167,248,184,vc(14));
3816 rect(screen2,207,191,224,208,vc(14));
3817 rect(screen2,231,191,248,208,vc(14));
3818 */
3819 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3820 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3821 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3822 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3823 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3824 int32_t screen_xofs=6;
3825 int32_t screen_yofs=25;
3826 int winh = 511;
3827 int32_t mul = 2;
3828
3829 yofs=16;
3830
3831 custom_vsync();
3832
3833 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3834
3835 // Suspend the current font while draw_text_button does its work
3836 FONT* oldfont = font;
3837
3838 font = get_zc_font(font_lfont_l);
3839
3840 int txt_x = 8*mul;
3841 int rbtn_x = 255*mul;
3842 int max_fpath_wid = rbtn_x-2-txt_x;
3843 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3844 // Interface
3845 switch(imagetype)
3846 {
3847 case 0:
3848 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3849 break;
3850
3851 case ftBMP:
3852 {
3853 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3854 int text_x = txt_x;
3855 int text_y = (216 + yofs) * mul;
3856 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3857 // int text_w = text_length(font, text.c_str());
3858 // int text_h = text_height(font);
3859 // static int grab_scale_tooltip_id = ttip_register_id();
3860 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3861 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3862
3863 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3864 break;
3865 }
3866
3867 case ftZGP:
3868 case ftQST:
3869 case ftZQT:
3870 case ftQSU:
3871 case ftTIL:
3872 case ftBIN:
3873 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3874 break;
3875 }
3876
3877 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3878 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3879
3880 if(bp==8)
3881 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3882 else
3883 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3884 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3885
3886 if(imagetype==ftBIN)
3887 {
3888 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3889 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3890 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3891 }
3892
3893 int fpath_y = (224+yofs)*mul;
3894 if(text_length(font,imagepath) <= max_fpath_wid)
3895 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3896 else
3897 {
3898 char buf[2052] = {0};
3899 strncpy(buf,imagepath,2048);
3900 int len = strlen(buf);
3901 char *ptr = buf;
3902 char *endptr = buf+len;
3903 char *it = endptr;
3904 int tmpy = fpath_y;
3905 int tmph = text_height(font)+1;
3906 while(true)
3907 {
3908 if(tmpy+tmph > (winh-2))
3909 break; //Out of space!
3910 char c = *it;
3911 bool end = !c;
3912 *it = 0;
3913 int newlen = text_length(font,ptr);
3914 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3915 {
3916 if(end) //No stored character, string ended
3917 {
3918 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3919 break;
3920 }
3921 char t[5];
3922 t[0] = c;
3923 for(int q = 1; q < 5; ++q)
3924 t[q] = it[q];
3925 strcpy(it,"...");
3926 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3927 for(int q = 0; q < 5; ++q)
3928 it[q] = t[q];
3929 tmpy += tmph;
3930 ptr = it;
3931 it = endptr;
3932 }
3933 else
3934 {
3935 *it = c;
3936 --it;
3937 }
3938 }
3939 }
3940 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3941 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3942 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3943 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3944
3945 //int32_t rectw = 16*mul;
3946 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3947 SCRFIX();
3948 font = oldfont;
3949 }
3950
3951 RGB_MAP rgb_table;
3952 COLOR_MAP imagepal_table;
3953
3954
3955 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3956 {
3957 //these are here to bypass compiler warnings about unused arguments
3958 x=x;
3959
3960 rgb->r = pal[y].r;
3961 rgb->g = pal[y].g;
3962 rgb->b = pal[y].b;
3963 }
3964
3965
3966 void load_imagebuf()
3967 {
3968 PACKFILE *f;
3969 //cache QRS
3970 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3971 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3972 // {
3973 // cached_rules[q] = quest_rules[q];
3974 // }
3975 bool compressed=false;
3976 bool encrypted=false;
3977 tiledata *hold=newtilebuf;
3978 zquestheader tempheader{};
3979
3980 if(imagebuf)
3981 {
3982 switch(imagetype)
3983 {
3984 case ftBMP:
3985 if (original_imagebuf_bitmap != imagebuf)
3986 destroy_bitmap((BITMAP*)imagebuf);
3987 destroy_bitmap(original_imagebuf_bitmap);
3988 break;
3989
3990 case ftZGP:
3991 case ftQST:
3992 case ftZQT:
3993 case ftQSU:
3994 case ftTIL:
3995 clear_tiles(grabtilebuf);
3996 break;
3997
3998 case ftBIN:
3999 free(imagebuf);
4000 break;
4001 }
4002
4003 imagebuf=NULL;
4004 original_imagebuf_bitmap=NULL;
4005 }
4006
4007 selx=sely=romofs=0;
4008 bp=4;
4009 imagetype=filetype(imagepath);
4010
4011 dword section_id;
4012 word section_version;
4013
4014 switch(imagetype)
4015 {
4016 case ftBMP:
4017 packfile_password("");
4018 memset(imagepal, 0, sizeof(PALETTE));
4019 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4020 imagesize = file_size_ex_password(imagepath,"");
4021 tilecount=0;
4022 create_rgb_table(&rgb_table, imagepal, NULL);
4023 rgb_map = &rgb_table;
4024 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4025
4026 if(!original_imagebuf_bitmap)
4027 {
4028 imagetype=0;
4029 }
4030 else
4031 {
4032 imagebuf = original_imagebuf_bitmap;
4033 imagebuf_bitmap_scale = 1;
4034 }
4035
4036 break;
4037
4038 case ftBIN:
4039 packfile_password("");
4040 imagesize = file_size_ex_password(imagepath, "");
4041 tilecount=0;
4042
4043 if(imagesize)
4044 {
4045 imagebuf = malloc(imagesize);
4046
4047 if(!readfile(imagepath,imagebuf,imagesize))
4048 {
4049 free(imagebuf);
4050 imagesize=0;
4051 imagetype=0;
4052 }
4053 }
4054
4055 break;
4056
4057 case ftTIL:
4058 packfile_password("");
4059 imagesize = file_size_ex_password(imagepath,"");
4060 f = pack_fopen_password(imagepath,F_READ,"");
4061
4062 if(!f)
4063 {
4064 goto error;
4065 }
4066
4067 if(!p_mgetl(&section_id,f))
4068 {
4069 goto error;
4070 }
4071
4072 if(section_id==ID_TILES)
4073 {
4074 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4075 {
4076 goto error;
4077 }
4078 }
4079
4080 error:
4081 pack_fclose(f);
4082 tilecount=count_tiles(grabtilebuf);
4083 break;
4084
4085 case ftZGP:
4086 packfile_password("");
4087 imagesize = file_size_ex_password(imagepath, "");
4088 f=pack_fopen_password(imagepath,F_READ,"");
4089
4090 if(!f)
4091 {
4092 goto error2;
4093 }
4094
4095 if(!p_mgetl(&section_id,f))
4096 {
4097 goto error2;
4098 }
4099
4100 if(section_id!=ID_GRAPHICSPACK)
4101 {
4102 goto error2;
4103 }
4104
4105 //section version info
4106 if(!p_igetw(&section_version,f))
4107 {
4108 goto error2;
4109 }
4110
4111 if(!read_deprecated_section_cversion(f))
4112 {
4113 goto error2;
4114 }
4115
4116 //tiles
4117 if(!p_mgetl(&section_id,f))
4118 {
4119 goto error2;
4120 }
4121
4122 if(section_id==ID_TILES)
4123 {
4124 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4125 {
4126 goto error2;
4127 }
4128 }
4129
4130 error2:
4131 pack_fclose(f);
4132 tilecount=count_tiles(grabtilebuf);
4133 break;
4134
4135 case ftQST:
4136 encrypted=true;
4137 case ftZQT:
4138 compressed=true;
4139 case ftQSU:
4140 packfile_password("");
4141 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4142 newtilebuf=grabtilebuf;
4143 byte skip_flags[4];
4144
4145 for(int32_t i=0; i<skip_max; ++i)
4146 {
4147 set_bit(skip_flags,i,1);
4148 }
4149
4150 set_bit(skip_flags,skip_tiles,0);
4151 set_bit(skip_flags,skip_header,0);
4152 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4153 if (ret)
4154 {
4155 imagetype=0;
4156 imagesize=0;
4157 clear_tiles(grabtilebuf);
4158 chop_path(imagepath);
4159 }
4160
4161 if (!ret && encrypted && compressed)
4162 {
4163 if(quest_access(imagepath, &tempheader) != 1)
4164 {
4165 imagetype=0;
4166 imagesize=0;
4167 clear_tiles(grabtilebuf);
4168 chop_path(imagepath);
4169 }
4170 }
4171
4172 //setPackfilePassword(NULL);
4173 newtilebuf=hold;
4174 tilecount=count_tiles(grabtilebuf);
4175 break;
4176 }
4177
4178 rgb_map = &zq_rgb_table;
4179 //restore cashed QRs / rules
4180
4181 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4182 // {
4183 // quest_rules[q] = cached_rules[q];
4184 // }
4185 }
4186
4187 static char bitstrbuf[32];
4188 bool leeching_from_tiles=false;
4189
4190 const char *bitlist(int32_t index, int32_t *list_size)
4191 {
4192 int32_t imported=2;
4193
4194 if(index>=0)
4195 {
4196 bound(index,0,leeching_from_tiles?2:1);
4197
4198 if(index==imported)
4199 {
4200 sprintf(bitstrbuf,"Imported");
4201 }
4202 else
4203 {
4204 sprintf(bitstrbuf,"%d",4<<index);
4205 }
4206
4207 return bitstrbuf;
4208 }
4209
4210 *list_size=leeching_from_tiles?3:2;
4211 return NULL;
4212 }
4213
4214 12 static ListData bit_list(bitlist, &font);
4215
4216 static DIALOG leech_dlg[] =
4217 {
4218 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4219 12 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4220 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4221 // 2
4222 12 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4223 12 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4224 12 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4225 // 5
4226 12 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4227 12 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4228 12 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4229 12 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4230 //9
4231 12 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4232 12 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4233
4234 12 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4235 12 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4236 12 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4237 12 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4238 12 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4239 //16
4240 12 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4241 12 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4242 12 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4243
4244 12 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4245 12 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4246 12 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4247
4248 12 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4249 12 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4250 12 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4251
4252 12 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4253 12 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4254 12 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4255
4256 12 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4257 12 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4258 12 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4259 12 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4260 12 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4261 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4262 };
4263
4264 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4265 {
4266 bool shift=true; // fix this!
4267 int32_t cst=0;
4268 int32_t currtile=start;
4269 int32_t height=0, width=0;
4270 byte *testtile = new byte[tilesize(tf32Bit)];
4271 byte imported_format=0;
4272 char updatestring[6];
4273 bool canadd;
4274 bool temp_canadd;
4275 bool duplicate;
4276 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4277 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4278 {
4279 0,0,0,0
4280 };
4281 BITMAP *status;
4282 status = create_bitmap_ex(8,240,140);
4283 clear_bitmap(status);
4284 sprintf(updatestring, "%d", LeechUpdate);
4285 leech_dlg[0].dp2=get_zc_font(font_lfont);
4286 leech_dlg[6].dp=updatestring;
4287
4288 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4289
4290 for(int32_t i=0; i<2; i++)
4291 {
4292 leech_dlg[i+7].flags=0;
4293 }
4294
4295 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4296
4297 for(int32_t i=0; i<12; i++)
4298 {
4299 leech_dlg[i+16].flags=0;
4300 }
4301
4302 for(int32_t i=0; i<4; i++)
4303 {
4304 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4305 }
4306
4307 leech_dlg[31].d1=0;
4308
4309 large_dialog(leech_dlg);
4310
4311 int32_t ret = do_zqdialog(leech_dlg,3);
4312
4313 if(ret==2)
4314 {
4315 delete[] testtile;
4316 return false;
4317 }
4318
4319 int32_t cdepth=leech_dlg[31].d1+1;
4320 int32_t newformat=0;
4321 auto lu = atoi(updatestring);
4322 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4323 if(LeechUpdate!=lu)
4324 {
4325 LeechUpdate=lu;
4326 zc_set_config("zquest","leech_update",LeechUpdate);
4327 }
4328 if(LeechUpdateTiles!=lut)
4329 {
4330 LeechUpdateTiles=lut;
4331 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4332 }
4333
4334 int32_t old_dupe[4];
4335 for(int32_t j=0; j<4; j++)
4336 {
4337 old_dupe[j] = DuplicateAction[j];
4338 for(int32_t i=0; i<3; i++)
4339 {
4340 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4341 {
4342 DuplicateAction[j]=i;
4343 }
4344 }
4345 }
4346 if(old_dupe[0] != DuplicateAction[0])
4347 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4348 if(old_dupe[1] != DuplicateAction[1])
4349 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4350 if(old_dupe[2] != DuplicateAction[2])
4351 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4352 if(old_dupe[3] != DuplicateAction[3])
4353 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4354
4355 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4356 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4357 {
4358 OnlyCheckNewTilesForDuplicates=ocntfd;
4359 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4360 }
4361
4362 leeching_from_tiles=false;
4363
4364 switch(imagetype)
4365 {
4366 case ftBIN:
4367 width=imagesize/128;
4368 height=1;
4369 break;
4370
4371 case ftZGP:
4372 case ftQST:
4373 case ftZQT:
4374 case ftQSU:
4375 case ftTIL:
4376 leeching_from_tiles=true;
4377 width=count_tiles(grabtilebuf);
4378 height=1;
4379 break;
4380
4381 case ftBMP:
4382 width=((((BITMAP*)imagebuf)->w)+15)/16;
4383 height=((((BITMAP*)imagebuf)->h)+15)/16;
4384 break;
4385 }
4386
4387 if(currtile+(width*height)>NEWMAXTILES)
4388 {
4389 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4390 {
4391 delete[] testtile;
4392 return false;
4393 }
4394 }
4395
4396 go_tiles();
4397 saved=false;
4398
4399 for(int32_t ty=0; ty<height; ty++) //for every row
4400 {
4401 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4402 {
4403 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4404 {
4405 FONT *oldfont = font;
4406 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4407 static bool created_tbar=false;
4408 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4409
4410 if(created_tbar)
4411 {
4412 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4413 }
4414 else
4415 {
4416 font = get_zc_font(font_lfont);
4417 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4418 font = oldfont;
4419 created_tbar=true;
4420 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4421 }
4422
4423 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4424 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4425 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4426 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4427 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4428 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4429 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4430 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4431 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4432 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4433 blit(status,screen,0, 0, 40, 20, 240, 140);
4434 SCRFIX();
4435 }
4436
4437 canadd=true;
4438
4439 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4440 {
4441 delete[] testtile;
4442 return true;
4443 }
4444
4445 switch(imagetype)
4446 {
4447 case ftBIN:
4448 break;
4449
4450 case ftZGP:
4451 case ftQST:
4452 case ftZQT:
4453 case ftQSU:
4454 case ftTIL:
4455 memset(testtile, 0, tilesize(tf32Bit));
4456 imported_format=grabtilebuf[tx].format;
4457
4458 switch(cdepth)
4459 {
4460 case 1: //4-bit
4461 newformat=tf4Bit;
4462
4463 switch(imported_format)
4464 {
4465 case tf4Bit:
4466 case tf8Bit:
4467 for(int32_t y=0; y<16; y++) //snag a tile
4468 {
4469 for(int32_t x=0; x<16; x+=2)
4470 {
4471 testtile[(y*8)+(x/2)]=
4472 (grabtilebuf[tx].data[y*16+x]&15)+
4473 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4474 }
4475 }
4476
4477 break;
4478 }
4479
4480 break;
4481
4482 case 2: //8-bit
4483 newformat=tf8Bit;
4484
4485 switch(imported_format)
4486 {
4487 case tf4Bit:
4488 unpack_tile(grabtilebuf, tx, 0, true);
4489 cst = cs&15;
4490 cst <<= CSET_SHFT;
4491
4492 for(int32_t i=0; i<256; i++)
4493 {
4494 if(!shift||unpackbuf[i]!=0)
4495 {
4496 unpackbuf[i]+=cst;
4497 }
4498 }
4499
4500 pack_tiledata(testtile, unpackbuf, tf8Bit);
4501 break;
4502
4503 case tf8Bit:
4504 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4505 break;
4506 }
4507
4508 break;
4509
4510 case 3: //original tile's bit depth
4511 newformat=imported_format;
4512 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4513 break;
4514 }
4515
4516 break;
4517
4518 case ftBMP:
4519 newformat=cdepth;
4520
4521 for(int32_t y=0; y<16; y++) //snag a tile
4522 {
4523 for(int32_t x=0; x<16; x+=2)
4524 {
4525 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4526 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4527 }
4528 }
4529
4530 break;
4531 }
4532
4533 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4534 {
4535 temp_canadd=true;
4536
4537 //check all tiles before this one
4538 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4539 {
4540 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4541 {
4542 if(DuplicateAction[flipping]>0)
4543 {
4544 if(keypressed())
4545 {
4546 delete[] testtile;
4547 return true;
4548 }
4549
4550 duplicate=(newformat==imported_format);
4551
4552 if(duplicate)
4553 {
4554 switch(flipping)
4555 {
4556 case 0: //normal
4557 if(dest[checktile].data!=NULL)
4558 {
4559 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4560 {
4561 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4562 {
4563 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4564 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4565 {
4566 duplicate=false;
4567 }
4568 }
4569 }
4570 }
4571
4572 break;
4573
4574 case 1: //horizontal
4575 if(dest[checktile].data!=NULL)
4576 {
4577 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4578 {
4579 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4580 {
4581 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4582 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4583 {
4584 duplicate=false;
4585 }
4586 }
4587 }
4588 }
4589
4590 break;
4591
4592 case 2: //vertical
4593 if(dest[checktile].data!=NULL)
4594 {
4595 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4596 {
4597 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4598 {
4599 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4600 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4601 {
4602 duplicate=false;
4603 }
4604 }
4605 }
4606 }
4607
4608 break;
4609
4610 case 3: //both
4611 if(dest[checktile].data!=NULL)
4612 {
4613 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4614 {
4615 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4616 {
4617 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4618 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4619 {
4620 duplicate=false;
4621 }
4622 }
4623 }
4624 }
4625
4626 break;
4627 }
4628 }
4629
4630 if(duplicate==true)
4631 {
4632 ++duplicates_found[flipping];
4633 ++total_duplicates_found;
4634
4635 if(DuplicateAction[flipping]>1)
4636 {
4637 ++total_duplicates_discarded;
4638 temp_canadd=false;
4639 }
4640 }
4641 }
4642
4643 canadd=canadd&&temp_canadd;
4644 }
4645 }
4646 }
4647
4648 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4649 dest[currtile].format=newformat;
4650
4651 if(dest[currtile].data!=NULL)
4652 {
4653 free(dest[currtile].data);
4654 }
4655
4656 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4657
4658 if(dest[currtile].data==NULL)
4659 {
4660 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4661 }
4662
4663 if(canadd==true)
4664 {
4665 /*
4666 for(int32_t y=0; y<16; y++)
4667 {
4668 for(int32_t x=0; x<8; x++)
4669 {
4670 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4671 }
4672 }
4673 */
4674 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4675 ++currtile;
4676 }
4677 }
4678 }
4679
4680 destroy_bitmap(status);
4681 delete[] testtile;
4682 return true;
4683 }
4684
4685 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4686 {
4687 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4688 byte format=defFormat;
4689 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4690
4691 switch(imagetype)
4692 {
4693 case ftZGP:
4694 case ftQST:
4695 case ftZQT:
4696 case ftQSU:
4697 case ftTIL:
4698 case ftBIN:
4699 case ftBMP:
4700 for(int32_t ty=0; ty<height; ty++)
4701 {
4702 for(int32_t tx=0; tx<width; tx++)
4703 {
4704 format=defFormat;
4705 switch(imagetype)
4706 {
4707 case ftZGP:
4708 case ftQST:
4709 case ftZQT:
4710 case ftQSU:
4711 case ftTIL:
4712 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4713 break;
4714 }
4715
4716 bool ever_did_unmasked = false;
4717
4718 for(int32_t y=0; y<16; y++)
4719 {
4720 for(int32_t x=0; x<16; x+=2)
4721 {
4722 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4723 if (masked)
4724 {
4725 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4726 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4727 }
4728 else
4729 {
4730 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4731 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4732 ever_did_unmasked = true;
4733 }
4734 if (format == tf4Bit)
4735 {
4736 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4737 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4738 }
4739 }
4740 }
4741
4742 if (ever_did_unmasked)
4743 newformat[(ty*TILES_PER_ROW)+tx] = format;
4744 }
4745 }
4746
4747 break;
4748
4749 default:
4750 for(int32_t i=0; i<200; i++)
4751 {
4752 for(int32_t j=0; j<256; j++)
4753 {
4754 dest[i][j]=0;
4755 }
4756
4757 newformat[i] = tf4Bit;
4758 }
4759
4760 break;
4761 }
4762 }
4763
4764 static void scale_imagebuf_bitmap()
4765 {
4766 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4767
4768 float scale = IMAGEBUF_SCALE;
4769 int nw = original_imagebuf_bitmap->w * scale;
4770 int nh = original_imagebuf_bitmap->h * scale;
4771 if (nw <= 0 || nh <= 0)
4772 return;
4773
4774 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4775 if (!scaled_bmp)
4776 return;
4777
4778 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4779 if (imagebuf != original_imagebuf_bitmap)
4780 destroy_bitmap((BITMAP*)imagebuf);
4781 imagebuf = scaled_bmp;
4782 }
4783
4784 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4785 void grab_tile(int32_t tile,int32_t &cs)
4786 {
4787 zq_allow_tile_draw_cache = true;
4788
4789 int window_w = 640+6+6, window_h = 480+25+6;
4790 int window_x=(zq_screen_w-window_w)/2;
4791 int window_y=(zq_screen_h-window_h)/2;
4792 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4793 int window_xofs = 0;
4794 int screen_xofs=6;
4795 int screen_yofs=25;
4796 int panel_yofs=0;
4797 int bwidth = 61*1.5;
4798 int bheight = 20*1.5;
4799 int button_x = 255*2;
4800 int grab_ok_button_y = 168*2 + 32;
4801 int leech_button_x = 117*2;
4802 int leech_button_y = 166*2 + 32;
4803 int grab_cancel_button_y = 192*2 + 32;
4804 int file_button_y = 216*2 + 32;
4805 int rec_button_x = 117*2;
4806 int rec_button_y = 192*2 + 32;
4807
4808 int screen_y1 = 24;
4809 int screen_y2 = screen_y1+320-1;
4810
4811 int crect_x = 184+190;
4812 int crect_y = 168*2 + 32;
4813 int crect_w = 8*2;
4814 int crect_h = 8*2;
4815
4816 int xrect_x = 640 + 12 - 21;
4817 int xrect_y = 5;
4818
4819 byte newtile[200][256];
4820 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4821 clear_bitmap(screen3);
4822 byte newformat[200];
4823
4824 memset(newtile, 0, 200*256);
4825 memset(newformat, 0, 200);
4826
4827 static EXT_LIST list[] =
4828 {
4829 { (char *)"All Files (*.*)", NULL },
4830 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4831 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4832 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4833 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4834 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4835 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4836 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4837 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4838 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4839 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4840 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4841 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4842 { NULL, NULL }
4843 };
4844
4845
4846 memset(cset_reduce_table, 0, 256);
4847 memset(col_diff,0,3*128);
4848 bool bdown=false;
4849 int done=0;
4850 int pal=0;
4851 int f=0;
4852 int black=vc(0),white=vc(15);
4853 int selwidth=1, selheight=1;
4854 int selx2=0, sely2=0;
4855 bool xreversed=false, yreversed=false;
4856 bool doleech=false, dofile=false, dopal=false;
4857
4858 int jwin_pal2[jcMAX];
4859 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4860
4861
4862 if(imagebuf==NULL)
4863 load_imagebuf();
4864
4865 calc_cset_reduce_table(imagepal, cs);
4866 calc_cset_reduce_table_8bit(imagepal);
4867 draw_grab_window();
4868 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4869 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4870
4871 while(gui_mouse_b())
4872 {
4873 /* do nothing */
4874 rest(1);
4875 }
4876
4877 do
4878 {
4879 HANDLE_CLOSE_ZQDLG();
4880 if(exiting_program) break;
4881 rest(4);
4882 bool redraw=false;
4883
4884 if(keypressed())
4885 {
4886 redraw=true;
4887
4888 switch(readkey()>>8)
4889 {
4890 case KEY_F:
4891 dofile=true;
4892 break;
4893
4894 case KEY_L:
4895 doleech=true;
4896 break;
4897
4898 case KEY_P:
4899 if(imagetype==ftBMP)
4900 {
4901 dopal=true;
4902 recolor=rcNone;
4903 calc_cset_reduce_table(imagepal, cs);
4904 }
4905
4906 break;
4907
4908 case KEY_ESC:
4909 done=1;
4910 break;
4911
4912 case KEY_ENTER_PAD:
4913 case KEY_ENTER:
4914 done=2;
4915 break;
4916
4917 case KEY_DOWN:
4918 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4919 else ++imagey;
4920
4921 break;
4922
4923 case KEY_UP:
4924 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4925 else --imagey;
4926
4927 break;
4928
4929 case KEY_RIGHT:
4930 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4931 else ++imagex;
4932
4933 break;
4934
4935 case KEY_LEFT:
4936 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4937 else --imagex;
4938
4939 break;
4940
4941 case KEY_PGDN:
4942 imagey+=10;
4943 break;
4944
4945 case KEY_PGUP:
4946 imagey-=10;
4947 break;
4948
4949 case KEY_HOME:
4950 imagex=imagey=0;
4951 break;
4952
4953 case KEY_EQUALS:
4954 case KEY_PLUS_PAD:
4955 cs = (cs<13) ? cs+1:0;
4956 if(recolor==rc4Bit)
4957 calc_cset_reduce_table(imagepal, cs);
4958 break;
4959
4960 case KEY_MINUS:
4961 case KEY_MINUS_PAD:
4962 cs = (cs>0) ? cs-1:13;
4963 if(recolor==rc4Bit)
4964 calc_cset_reduce_table(imagepal, cs);
4965 break;
4966
4967 case KEY_S:
4968 if(grabmode==1) grabmode=8;
4969 else if(grabmode==8) grabmode=16;
4970 else grabmode=1;
4971
4972 break;
4973
4974 case KEY_COMMA:
4975 if (imagetype == ftBMP)
4976 {
4977 imagebuf_bitmap_scale--;
4978 if (imagebuf_bitmap_scale == 0)
4979 imagebuf_bitmap_scale = -2;
4980 scale_imagebuf_bitmap();
4981 }
4982 break;
4983 case KEY_STOP:
4984 if (imagetype == ftBMP)
4985 {
4986 imagebuf_bitmap_scale++;
4987 if (imagebuf_bitmap_scale == -1)
4988 imagebuf_bitmap_scale = 1;
4989 scale_imagebuf_bitmap();
4990 }
4991 break;
4992
4993 case KEY_1:
4994 if(recolor==rc8Bit)
4995 recolor=rcNone;
4996 //imagex=(imagex*bp)>>3;
4997 bp=1;
4998 //imagex<<=3;
4999 nesmode=false;
5000 break;
5001
5002 case KEY_2:
5003 if(recolor==rc8Bit)
5004 recolor=rcNone;
5005 //imagex=(imagex*bp)>>3;
5006 bp=2;
5007 //imagex<<=2;
5008 nesmode=false;
5009 break;
5010
5011 case KEY_N:
5012 if(recolor==rc8Bit)
5013 recolor=rcNone;
5014 //imagex=(imagex*bp)>>3;
5015 bp=2;
5016 //imagex<<=2;
5017 nesmode=true;
5018 break;
5019
5020 case KEY_4:
5021 if(recolor==rc8Bit)
5022 recolor=rcNone;
5023 //imagex=(imagex*bp)>>3;
5024 bp=4;
5025 //imagex<<=1;
5026 nesmode=false;
5027 break;
5028
5029 case KEY_8:
5030 //imagex=(imagex*bp)>>3;
5031 bp=8;
5032 break;
5033
5034 case KEY_B:
5035 if(bp==2&&!nesmode)
5036 {
5037 nesmode=true;
5038 }
5039 else
5040 {
5041 nesmode=false;
5042 bp<<=1;
5043
5044 if(bp==16)
5045 {
5046 bp=1;
5047 //imagex<<=3;
5048 }
5049 else
5050 {
5051 //imagex>>=1;
5052 }
5053 }
5054
5055 break;
5056
5057 case KEY_M:
5058 romtilemode=(romtilemode+1)%4;
5059 break;
5060
5061 case KEY_Z:
5062 if(romofs>0) --romofs;
5063
5064 break;
5065
5066 case KEY_X:
5067 ++romofs;
5068 break;
5069
5070 case KEY_R:
5071 if(pal)
5072 {
5073 dopal=true;
5074 }
5075
5076 if(recolor!=rcNone)
5077 recolor=rcNone;
5078 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5079 {
5080 bp=8;
5081 recolor=rc8Bit;
5082 calc_cset_reduce_table_8bit(imagepal);
5083 }
5084 else
5085 {
5086 if(bp==8)
5087 bp=4;
5088 recolor=rc4Bit;
5089 calc_cset_reduce_table(imagepal, cs);
5090 }
5091 break;
5092
5093 default:
5094 redraw=false;
5095 }
5096
5097 clear_keybuf();
5098
5099 if(imagex<0) imagex=0;
5100
5101 if(imagey<0) imagey=0;
5102
5103 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5104 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5105 }
5106
5107 //boogie!
5108 if(gui_mouse_b()==1 && !bdown)
5109 {
5110 int x=gui_mouse_x();
5111 int y=gui_mouse_y();
5112 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5113 if(do_x_button(screen, xrect_x, xrect_y))
5114 done=1;
5115
5116 if(!bdown)
5117 {
5118 bool regrab=false;
5119 bdown=true;
5120 FONT* oldfont = font;
5121 font = get_zc_font(font_lfont_l);
5122
5123 if(y>=screen_y1 && y<=screen_y2)
5124 {
5125 do
5126 {
5127 HANDLE_CLOSE_ZQDLG();
5128 if(exiting_program) break;
5129 int x = (gui_mouse_x()-screen_xofs) / 2;
5130 int y = (gui_mouse_y()-screen_yofs) / 2;
5131
5132 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5133
5134 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5135 {
5136 selx=vbound((x/grabmode)*grabmode,0,304);
5137 sely=vbound((y/grabmode)*grabmode,0,144);
5138 selx2=selx;
5139 sely2=sely;
5140 selwidth=1;
5141 selheight=1;
5142 xreversed=false;
5143 yreversed=false;
5144 }
5145 else
5146 {
5147 if(xreversed)
5148 {
5149 zc_swap(selx, selx2);
5150 xreversed=false;
5151 }
5152
5153 if(yreversed)
5154 {
5155 zc_swap(sely, sely2);
5156 yreversed=false;
5157 }
5158
5159 selx2=vbound((x/grabmode)*grabmode,0,304);
5160 sely2=vbound((y/grabmode)*grabmode,0,144);
5161 selwidth=1+(abs(selx2-selx))/16;
5162 selheight=1+(abs(sely2-sely))/16;
5163
5164 if(selx2<selx)
5165 {
5166 zc_swap(selx, selx2);
5167 xreversed=true;
5168 }
5169
5170 if(sely2<sely)
5171 {
5172 zc_swap(sely, sely2);
5173 yreversed=true;
5174 }
5175 }
5176
5177 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5178 bool redraw = changed || !(f%8);
5179
5180 if(redraw)
5181 {
5182 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5183 if(changed)
5184 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5185 if(f&8)
5186 {
5187 static const int w = 32;
5188 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5189 }
5190 }
5191 else custom_vsync();
5192
5193 ++f;
5194 }
5195 while(gui_mouse_b());
5196 }
5197 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5198 {
5199 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5200 done=2;
5201 }
5202 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5203 {
5204 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5205 {
5206 doleech=true;
5207 }
5208 }
5209 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5210 {
5211 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5212 done=1;
5213 }
5214 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5215 {
5216 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5217 {
5218 dofile=true;
5219 }
5220 }
5221 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5222 {
5223 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5224 {
5225 if(pal)
5226 {
5227 dopal = true;
5228 }
5229
5230 if(recolor!=rcNone)
5231 recolor=rcNone;
5232 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5233 {
5234 bp=8;
5235 recolor=rc8Bit;
5236 calc_cset_reduce_table_8bit(imagepal);
5237 }
5238 else
5239 {
5240 if(bp==8)
5241 bp=4;
5242 recolor=rc4Bit;
5243 calc_cset_reduce_table(imagepal, cs);
5244 }
5245 redraw=true;
5246 }
5247 }
5248 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5249 {
5250 regrab=true;
5251 grabmask^=1;
5252 }
5253 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5254 {
5255 regrab=true;
5256 grabmask^=2;
5257 }
5258 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5259 {
5260 regrab=true;
5261 grabmask^=4;
5262 }
5263 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5264 {
5265 regrab=true;
5266 grabmask^=8;
5267 }
5268
5269 if(regrab)
5270 {
5271 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5272 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5273 redraw=true;
5274 }
5275
5276 font = oldfont;
5277 }
5278 }
5279
5280 if(gui_mouse_b()==0)
5281 bdown=false;
5282
5283 if(dofile)
5284 {
5285 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5286 {
5287 zc_set_palette(RAMpal);
5288 pal=0;
5289 white=vc(15);
5290 black=vc(0);
5291 strcpy(imagepath,temppath);
5292 load_imagebuf();
5293 imagex=imagey=0;
5294 calc_cset_reduce_table(imagepal, cs);
5295 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5296 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5297 }
5298
5299 while(key[KEY_ESC])
5300 {
5301 poll_keyboard();
5302 /* do nothing */
5303 rest(1);
5304 }
5305
5306 clear_keybuf();
5307 dofile=false;
5308 redraw=true;
5309 }
5310
5311 if(doleech)
5312 {
5313 if(leech_tiles(newtilebuf,tile,cs))
5314 {
5315 done=1;
5316 }
5317 else
5318 {
5319 while(key[KEY_ESC])
5320 {
5321 poll_keyboard();
5322 /* do nothing */
5323 rest(1);
5324 }
5325
5326 clear_keybuf();
5327 redraw=true;
5328 }
5329
5330 doleech=false;
5331 }
5332
5333 if(dopal)
5334 {
5335 pal^=1;
5336
5337 if(pal)
5338 {
5339 get_bw(imagepal,black,white);
5340
5341 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5342 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5343 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5344 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5345 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5346 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5347 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5348 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5349 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5350 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5351 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5352 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5353 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5354 gui_bg_color=jwin_pal[jcBOX];
5355 gui_fg_color=jwin_pal[jcBOXFG];
5356 jwin_set_colors(jwin_pal);
5357 }
5358 else
5359 {
5360 white=vc(15);
5361 black=vc(0);
5362
5363 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5364 gui_bg_color=jwin_pal[jcBOX];
5365 gui_fg_color=jwin_pal[jcBOXFG];
5366 jwin_set_colors(jwin_pal);
5367 }
5368
5369 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5370
5371 dopal=false;
5372 redraw=true;
5373 }
5374
5375 if(redraw)
5376 {
5377 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5378 }
5379 else
5380 {
5381 custom_vsync();
5382 }
5383
5384 if((f%8)==0)
5385 {
5386 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5387
5388 int selxl = selx* 2;
5389 int selyl = sely* 2;
5390 int w = 32;
5391
5392 if(f&8)
5393 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5394
5395 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5396 }
5397
5398 // SCRFIX();
5399 ++f;
5400
5401 }
5402 while(!done);
5403
5404 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5405 gui_bg_color=jwin_pal[jcBOX];
5406 gui_fg_color=jwin_pal[jcBOXFG];
5407 jwin_set_colors(jwin_pal);
5408
5409
5410 if(done==2)
5411 {
5412 go_tiles();
5413 saved=false;
5414
5415 for(int y=0; y<selheight; y++)
5416 {
5417 for(int x=0; x<selwidth; x++)
5418 {
5419 int temptile=tile+((TILES_PER_ROW*y)+x);
5420 int format=(bp==8) ? tf8Bit : tf4Bit;
5421
5422 if(newtilebuf[temptile].data!=NULL)
5423 free(newtilebuf[temptile].data);
5424
5425 newtilebuf[temptile].format=format;
5426 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5427
5428 if(newtilebuf[temptile].data==NULL)
5429 {
5430 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5431 break;
5432 }
5433
5434 for(int i=0; i<256; i++)
5435 {
5436 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5437 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5438 }
5439
5440 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5441 }
5442 }
5443 }
5444
5445 destroy_bitmap(screen3);
5446
5447 if(pal)
5448 zc_set_palette(RAMpal);
5449
5450 recolor=rcNone;
5451 calc_cset_reduce_table(imagepal, cs);
5452 register_blank_tiles();
5453 popup_zqdialog_end();
5454
5455 zq_allow_tile_draw_cache = false;
5456 }
5457
5458 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5459 bool tile_is_used(int32_t tile)
5460 {
5461 return used_tile_table[tile];
5462 }
5463 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5464 {
5465 draw_tiles(screen2, first, cs, f, true);
5466 }
5467 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5468 {
5469 clear_bitmap(dest);
5470 BITMAP *buf = create_bitmap_ex(8,16,16);
5471
5472 int32_t w = 16;
5473 int32_t h = 16;
5474
5475 if(large)
5476 {
5477 w *=2;
5478 h *=2;
5479 }
5480
5481 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5482 {
5483 int32_t x = (i%TILES_PER_ROW)<<4;
5484 int32_t y = (i/TILES_PER_ROW)<<4;
5485 int32_t l = 16;
5486
5487 if(large)
5488 {
5489 x*=2;
5490 y*=2;
5491 l*=2;
5492 }
5493
5494 l-=2;
5495
5496 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5497 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5498 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5499 {
5500 if(!true_empty) //Use pure color 0; no effects
5501 {
5502 if (InvalidBG == 2)
5503 {
5504 draw_checkerboard(dest, x, y, w);
5505 }
5506 else if(InvalidBG == 1)
5507 {
5508 for(int32_t dy=0; dy<=l+1; dy++)
5509 {
5510 for(int32_t dx=0; dx<=l+1; dx++)
5511 {
5512 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5513 }
5514 }
5515 }
5516 else
5517 {
5518 for(int32_t dy=0; dy<=l+1; dy++)
5519 {
5520 for(int32_t dx=0; dx<=l+1; dx++)
5521 {
5522 dest->line[dy+(y)][dx+(x)]=vc(0);
5523 }
5524 }
5525 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5526 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5527 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5528 }
5529 }
5530 }
5531 else
5532 {
5533 puttile16(buf,first+i,0,0,cs,0);
5534 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5535 }
5536
5537 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5538 {
5539 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5540 }
5541 }
5542
5543 destroy_bitmap(buf);
5544 }
5545
5546 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5547 {
5548 int32_t yofs=3;
5549 BITMAP *buf = create_bitmap_ex(8,16,16);
5550 int32_t mul = 2;
5551 FONT *tfont = get_zc_font(font_pfont);
5552
5553 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5554 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5555 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5556 tfont = get_zc_font(font_lfont_l);
5557
5558 // Copied tile and numbers
5559 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5560 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5561 if(copy>=0)
5562 {
5563 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5564 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5565
5566 if(copycnt>1)
5567 {
5568 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5569 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5570 }
5571 else
5572 {
5573 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5574 }
5575 }
5576 else // No tiles copied
5577 {
5578 if (InvalidBG == 2)
5579 {
5580 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5581 }
5582 else if(InvalidBG == 1)
5583 {
5584 for(int32_t dy=0; dy<16*mul; dy++)
5585 {
5586 for(int32_t dx=0; dx<16*mul; dx++)
5587 {
5588 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5589 }
5590 }
5591 }
5592 else
5593 {
5594 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5595 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5596 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5597 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5598 }
5599 }
5600
5601
5602 // Current tile
5603 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5604 puttile16(buf,tile,0,0,cs,0);
5605 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5606
5607 // Current selection mode
5608 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5609 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5610
5611 if(tile>tile2)
5612 {
5613 zc_swap(tile,tile2);
5614 }
5615
5616 char tbuf[8];
5617 tbuf[0]=0;
5618
5619 if(tile2!=tile)
5620 {
5621 sprintf(tbuf,"-%d",tile2);
5622 }
5623
5624 // Current tile and CSet text
5625 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5626 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5627 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5628
5629 FONT *tf = font;
5630 font = tfont;
5631
5632 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5633 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5634 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5635 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5636 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5637
5638 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5639 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5640 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5641 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5642
5643 font = tf;
5644
5645 int32_t w = 640;
5646 int32_t h = 480;
5647 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5648 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5649 int32_t screen_xofs=window_xofs+6;
5650 int32_t screen_yofs=window_yofs+25;
5651
5652 custom_vsync();
5653 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5654 SCRFIX();
5655 destroy_bitmap(buf);
5656 }
5657
5658 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5659 {
5660 int32_t yofs=3;
5661 BITMAP *buf = create_bitmap_ex(8,16,16);
5662 int32_t mul = 2;
5663 FONT *tfont = get_zc_font(font_pfont);
5664
5665 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5666 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5667 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5668 tfont = get_zc_font(font_lfont_l);
5669
5670 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5671
5672 if(copy>=0)
5673 {
5674 puttile16(buf,copy,0,0,cs,flip);
5675 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5676 }
5677 else
5678 {
5679 if (InvalidBG == 2)
5680 {
5681 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5682 }
5683 else if(InvalidBG == 1)
5684 {
5685 for(int32_t dy=0; dy<16*mul; dy++)
5686 {
5687 for(int32_t dx=0; dx<16*mul; dx++)
5688 {
5689 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5690 }
5691 }
5692 }
5693 else
5694 {
5695 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5696 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5697 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5698 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5699 }
5700 }
5701
5702 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5703 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5704 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5705
5706 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5707 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5708
5709 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5710 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5711
5712 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5713 {
5714 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5715 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5716 }
5717
5718 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5719 puttile16(buf,tile,0,0, cs,
5720 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5721 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5722
5723 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5724 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5725 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5726 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5727
5728 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5729 {
5730 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5731 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5732 }
5733
5734 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5735 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5736 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5737 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5738
5739
5740 int32_t w = 640;
5741 int32_t h = 480;
5742 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5743 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5744 int32_t screen_xofs=window_xofs+6;
5745 int32_t screen_yofs=window_yofs+25;
5746
5747 custom_vsync();
5748 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5749 SCRFIX();
5750 destroy_bitmap(buf);
5751 }
5752 /*
5753 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5754 {
5755 buf[t].format=format;
5756 if (buf[t].data!=NULL)
5757 {
5758 free(buf[t].data);
5759 }
5760 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5761 if (buf[t].data==NULL)
5762 {
5763 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5764 }
5765 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5766 {
5767 buf[t].data[i]=0;
5768 }
5769 }
5770 */
5771
5772 int32_t hide_used()
5773 {
5774 show_only_unused_tiles ^= 1;
5775 return D_O_K;
5776 }
5777 int32_t hide_unused()
5778 {
5779 show_only_unused_tiles ^= 2;
5780 return D_O_K;
5781 }
5782 int32_t hide_blank()
5783 {
5784 show_only_unused_tiles ^= 4;
5785 return D_O_K;
5786 }
5787 int32_t hide_8bit_marker()
5788 {
5789 show_only_unused_tiles ^= 8;
5790 return D_O_K;
5791 }
5792
5793 enum
5794 {
5795 MENUID_SELTILE_VIEW_HIDE_USED,
5796 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5797 MENUID_SELTILE_VIEW_HIDE_BLANK,
5798 MENUID_SELTILE_VIEW_HIDE_8BIT,
5799 };
5800
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_view_menu
5801 60 {
5802
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5803
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5804
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5805
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5806 };
5807
5808 12 static std::function<void(int)> select_tile_color_depth_cb;
5809
5810 static void set_tile_color_depth_4()
5811 {
5812 select_tile_color_depth_cb(tf4Bit);
5813 }
5814 static void set_tile_color_depth_8()
5815 {
5816 select_tile_color_depth_cb(tf8Bit);
5817 }
5818 enum
5819 {
5820 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5821 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5822 };
5823
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_color_depth_menu
5824 36 {
5825
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5826
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5827 };
5828
5829 //returns the row the tile is in on its page
5830 int32_t tile_page_row(int32_t tile)
5831 {
5832 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5833 }
5834
5835 enum {ti_none, ti_encompass, ti_broken};
5836
5837 //striped check and striped selection
5838 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5839 {
5840 int32_t cmb_first = cmb.o_tile;
5841 int32_t cmb_last = cmb.o_tile;
5842 do
5843 {
5844 cmb_last = cmb.tile;
5845 animate(cmb, true);
5846 }
5847 while(cmb.tile != cmb.o_tile);
5848 reset_combo_animation(cmb);
5849 cmb_first += offset;
5850 cmb_last += offset;
5851
5852 if(cmb_first > selection_last || cmb_last < selection_first)
5853 return ti_none;
5854 if(cmb_first >= selection_first && cmb_last <= selection_last)
5855 return ti_encompass;
5856
5857 do
5858 {
5859 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5860 {
5861 reset_combo_animation(cmb);
5862 return ti_broken; //contained, but non-encompassing.
5863 }
5864 animate(cmb, true);
5865 }
5866 while(cmb.tile != cmb.o_tile);
5867 reset_combo_animation(cmb);
5868 return ti_none;
5869 }
5870 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5871 {
5872 // if selection is before or after check...
5873 if((check_first>selection_last)||(selection_first>check_last))
5874 {
5875 return ti_none;
5876 }
5877
5878 // if selection envelopes check
5879 if((selection_first<=check_first)&&(selection_last>=check_last))
5880 {
5881 return ti_encompass; //encompass
5882 }
5883
5884 //everything else is a break
5885 return ti_broken; //intersect
5886 }
5887
5888
5889
5890 //rectangular check and striped selection
5891 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5892 {
5893 int32_t ret1=-1, ret2=-1;
5894
5895 for(int32_t i=0; i<check_height; ++i)
5896 {
5897 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5898 int32_t check_last=check_first+check_width-1;
5899 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5900
5901 if(ret2==ti_broken)
5902 {
5903 return ti_broken;
5904 }
5905
5906 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5907 }
5908
5909 if(ret1==ti_encompass)
5910 {
5911 if((TILEROW(selection_first)<=check_top) &&
5912 (TILEROW(selection_last)>=(check_top+check_height-1)))
5913 {
5914 return ti_encompass;
5915 }
5916 else
5917 {
5918 return ti_broken;
5919 }
5920 }
5921
5922 return ti_none;
5923 }
5924
5925
5926 //striped check and rectangular selection
5927 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5928 {
5929 if(selection_width < TILES_PER_ROW)
5930 {
5931 int32_t cmb_first = cmb.o_tile;
5932 int32_t cmb_last = cmb.o_tile;
5933 do
5934 {
5935 cmb_last = cmb.tile;
5936 animate(cmb, true);
5937 }
5938 while(cmb.tile != cmb.o_tile);
5939 reset_combo_animation(cmb);
5940 cmb_first += offset;
5941 cmb_last += offset;
5942
5943 if((TILEROW(cmb_first)>=selection_top) &&
5944 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5945 (TILECOL(cmb_first)>=selection_left) &&
5946 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5947 {
5948 return ti_encompass;
5949 }
5950 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5951 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5952 {
5953 return ti_none;
5954 }
5955
5956 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5957 {
5958 int32_t firstcol = TILECOL(cmb_first);
5959 int32_t lastcol = TILECOL(cmb_last);
5960
5961 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5962 return ti_none;
5963 else //handle skip x
5964 {
5965 do
5966 {
5967 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5968 {
5969 reset_combo_animation(cmb);
5970 return ti_broken;
5971 }
5972 animate(cmb, true);
5973 }
5974 while(cmb.tile != cmb.o_tile);
5975 reset_combo_animation(cmb);
5976 return ti_none;
5977 }
5978 }
5979 else //multi-row combo...
5980 {
5981 int32_t row = TILEROW(cmb_first);
5982
5983 do
5984 {
5985 if(row < selection_top || row > selection_top+selection_height-1)
5986 {
5987 //This row isn't in the selection; skip to next row
5988 do
5989 {
5990 animate(cmb,true);
5991 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5992 }
5993 while(TILEROW(cmb.tile) == row);
5994 row = TILEROW(cmb.tile);
5995 continue;
5996 }
5997
5998 //This row IS in the selection; check each tile.
5999 do
6000 {
6001 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
6002 {
6003 reset_combo_animation(cmb);
6004 return ti_broken;
6005 }
6006 animate(cmb, true);
6007 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
6008 }
6009 while(TILEROW(cmb.tile) == row);
6010 row = TILEROW(cmb.tile);
6011 }
6012 while(cmb.tile != cmb.o_tile);
6013
6014 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
6015 }
6016 }
6017
6018 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
6019 }
6020 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6021 {
6022 if(selection_width < TILES_PER_ROW)
6023 {
6024 if((check_last-check_first+1<=selection_width) &&
6025 (TILEROW(check_first)>=selection_top) &&
6026 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6027 (TILECOL(check_first)>=selection_left) &&
6028 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6029 {
6030 return ti_encompass;
6031 }
6032 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6033 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6034 {
6035 return ti_none;
6036 }
6037
6038 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6039
6040 //one last base case: the strip we're interested in only lies along one row
6041 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6042 {
6043 int32_t cfcol = check_first%TILES_PER_ROW;
6044 int32_t clcol = check_last%TILES_PER_ROW;
6045
6046 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6047 return ti_none;
6048 else
6049 return ti_broken;
6050 }
6051 else
6052 {
6053 //recursively cut the strip into substrips which lie entirely on one row
6054 int32_t currow = check_first/TILES_PER_ROW;
6055 int32_t endrow = check_last/TILES_PER_ROW;
6056 int32_t accum = 0;
6057 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6058
6059 for(++currow; currow<endrow; currow++)
6060 {
6061 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6062 }
6063
6064 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6065
6066 if(accum > 0)
6067 return ti_broken;
6068
6069 return ti_none;
6070 }
6071 }
6072
6073 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6074 }
6075
6076 //rectangular check and rectangular selection
6077 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6078 {
6079 if((check_left>=selection_left) &&
6080 (check_left+check_width<=selection_left+selection_width) &&
6081 (check_top>=selection_top) &&
6082 (check_top+check_height<=selection_top+selection_height))
6083 {
6084 return ti_encompass;
6085 }
6086 else
6087 {
6088 for(int32_t i=check_top; i<check_top+check_height; ++i)
6089 {
6090 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6091 {
6092 return ti_broken;
6093 }
6094 }
6095 }
6096
6097 return ti_none;
6098 }
6099
6100
6101
6102
6103 static DIALOG move_textbox_list_dlg[] =
6104 {
6105 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6106 12 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6107 12 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6108 12 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6109 12 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6110 12 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6111 12 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6112 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6113 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6114 };
6115
6116 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6117 {
6118 char buf1[512] = {0};
6119 char buf2[512] = {0};
6120 large_dialog(move_textbox_list_dlg);
6121 DIALOG& tbox = move_textbox_list_dlg[3];
6122 {
6123 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6124 int indx = 0, word_indx = 0;
6125 for(char c : msg)
6126 {
6127 if(c == ' ' || c == '\n')
6128 word_indx = indx;
6129 buf1[indx++] = c;
6130 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6131 {
6132 buf1[word_indx] = 0;
6133 strcpy(buf2, msg.c_str()+word_indx+1);
6134 break;
6135 }
6136 }
6137 }
6138
6139 move_textbox_list_dlg[0].dp = (void*)title;
6140 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6141 move_textbox_list_dlg[1].dp = buf1;
6142 move_textbox_list_dlg[2].dp = buf2;
6143 tbox.dp = textbox;
6144 tbox.d2 = 0;
6145 auto tby = tbox.y;
6146 auto tbh = tbox.h;
6147 if(!buf2[0])
6148 {
6149 auto diff = move_textbox_list_dlg[2].h;
6150 tbox.y -= diff;
6151 tbox.h += diff;
6152 }
6153
6154 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6155 position_mouse_z(0);
6156 tbox.y = tby;
6157 tbox.h = tbh;
6158
6159 return ret == 4;
6160 }
6161
6162 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6163 {
6164 return a==0?b:a==1?c:d;
6165 }
6166
6167 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6168 {
6169 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6170 int i = ti_none;
6171 auto t = ref->getTile() + ref->offset();
6172
6173 if(combo_ref)
6174 {
6175 if(proc.rect)
6176 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6177 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6178 }
6179 else if(proc.rect)
6180 {
6181 if(ref->h > 1)
6182 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6183 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6184 }
6185 else
6186 {
6187 if(ref->h > 1)
6188 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6189 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6190 }
6191
6192 bool in = i != ti_none, out = i != ti_encompass;
6193 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6194 {
6195 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6196 if(proc.rect)
6197 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6198 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6199 if(i != ti_none)
6200 in = true;
6201 if(i != ti_encompass)
6202 out = true;
6203 }
6204 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6205
6206 if(i != ti_none && ref->getTile() != 0)
6207 {
6208 if(mode == Mode::CHECK_ALL)
6209 {
6210 move_refs.emplace_back(std::move(ref));
6211 return true;
6212 }
6213 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6214 {
6215 if(warning_flood || warning_list.tellp() >= 65000)
6216 {
6217 if(!warning_flood)
6218 warning_list << "...\n...\n...\nmany others";
6219 warning_flood = true;
6220 }
6221 else
6222 warning_list << ref->name << '\n';
6223 }
6224 else if(i==ti_encompass)
6225 {
6226 move_refs.emplace_back(std::move(ref));
6227 return true;
6228 }
6229 }
6230 return false;
6231 }
6232
6233 bool TileMoveList::check_prot()
6234 {
6235 if(!TileProtection)
6236 return true;
6237 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6238
6239 warning_flood = false;
6240 warning_list.clear();
6241
6242 return ret;
6243 }
6244
6245 void TileMoveList::add_diff(int diff)
6246 {
6247 for(auto& ref : move_refs)
6248 ref->addTile(diff);
6249 }
6250
6251 //from 'combo.h'
6252 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6253 {
6254 int i = ti_none;
6255 auto c = ref->getCombo();
6256
6257 if(ref->no_move)
6258 processed_combos[c] = true;
6259 else processed_combos[c]; //inserts element if does not exist
6260 i = move_intersection_ss(c, c, proc._first, proc._last);
6261
6262 if(i != ti_none && ref->getCombo() != 0)
6263 {
6264 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6265 {
6266 if(ComboProtection)
6267 {
6268 if(warning_flood || warning_list.tellp() >= 65000)
6269 {
6270 if(!warning_flood)
6271 warning_list << "...\n...\n...\nmany others";
6272 warning_flood = true;
6273 }
6274 else
6275 warning_list << ref->name << '\n';
6276 }
6277 }
6278 else if(i==ti_encompass)
6279 {
6280 move_refs.emplace_back(std::move(ref));
6281 return true;
6282 }
6283 }
6284 return false;
6285 }
6286
6287 bool ComboMoveList::check_prot()
6288 {
6289 if(!ComboProtection)
6290 return true;
6291 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6292 bool subset_header = false;
6293 for(int q = 0; q < 2; ++q)
6294 {
6295 bool is_dest = (q==1);
6296 if(!is_dest && !source_process)
6297 continue;
6298 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6299 for(auto it = subset.begin(); it != subset.end();)
6300 {
6301 auto s = *it;
6302 if(warning_flood || warning_list.tellp() >= 65000)
6303 {
6304 if(!warning_flood)
6305 warning_list << "...\n...\n...\nmany others";
6306 warning_flood = true;
6307 break;
6308 }
6309 set<int> in_set, out_set;
6310 bool no_move = is_dest;
6311 for(int c : *s)
6312 {
6313 int i = move_intersection_ss(c, c, proc._first, proc._last);
6314 if(i != ti_none)
6315 in_set.insert(c);
6316 if(i != ti_encompass)
6317 out_set.insert(c);
6318 if(!no_move)
6319 {
6320 auto it = processed_combos.find(c);
6321 if(it != processed_combos.end() && it->second)
6322 no_move = true;
6323 }
6324 }
6325 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6326 if(i == ti_encompass && !no_move)
6327 {
6328 it = subset.erase(it);
6329 continue;
6330 }
6331 if(i == ti_none)
6332 {
6333 ++it;
6334 continue;
6335 }
6336
6337 if(!subset_header)
6338 {
6339 subset_header = true;
6340 warning_list << "===== Broken Relative Combo Groups =====\n";
6341 }
6342 bool comma = false;
6343 warning_list << "In(";
6344 for(int c : in_set)
6345 {
6346 if(comma)
6347 warning_list << ",";
6348 else comma = true;
6349 warning_list << c;
6350 }
6351 warning_list << "),Out(";
6352 comma = false;
6353 for(int c : out_set)
6354 {
6355 if(comma)
6356 warning_list << ",";
6357 else comma = true;
6358 warning_list << c;
6359 }
6360 warning_list << ")\n";
6361 it = subset.erase(it);
6362 }
6363 }
6364 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6365
6366 processed_combos.clear();
6367 warning_flood = false;
6368 warning_list.clear();
6369
6370 return ret;
6371 }
6372
6373 void ComboMoveList::add_diff(int diff)
6374 {
6375 for(auto& ref : move_refs)
6376 ref->addCombo(diff);
6377 }
6378
6379 static void collect_subscreen_tiles(SubscrWidget& widget, TileMoveList& list)
6380 {
6381 if (auto w = dynamic_cast<SW_2x2Frame*>(&widget))
6382 {
6383 list.add_tile(&w->tile, 2, 2, "2x2 Frame");
6384 }
6385 else if (auto w = dynamic_cast<SW_TriFrame*>(&widget))
6386 {
6387 list.add_tile(&w->frame_tile, 6, 3, "McGuffin Frame - Frame");
6388 list.add_tile(&w->piece_tile, "McGuffin Frame - Piece");
6389 }
6390 else if (auto w = dynamic_cast<SW_McGuffin*>(&widget))
6391 {
6392 list.add_tile(&w->tile, "McGuffin Piece");
6393 }
6394 else if (auto w = dynamic_cast<SW_TileBlock*>(&widget))
6395 {
6396 list.add_tile(&w->tile, w->w, w->h, "TileBlock");
6397 }
6398 else if (auto w = dynamic_cast<SW_MiniTile*>(&widget))
6399 {
6400 if (w->tile == -1)
6401 return;
6402
6403 list.add_tile(&w->tile, "MiniTile");
6404 }
6405 else if (auto w = dynamic_cast<SW_GaugePiece*>(&widget))
6406 {
6407 int fr = w->frames ? w->frames : 1;
6408 fr = fr * (1+(w->get_per_container()/(w->unit_per_frame+1)));
6409 if(!(w->flags&SUBSCR_GAUGE_FULLTILE))
6410 fr = (fr/4_zf).getCeil();
6411
6412 for(auto q = 0; q < 4; ++q)
6413 {
6414 list.add_tile(&w->mts[q].mt_tile, fr, 1, fmt::format("Gauge Tile {}", q));
6415 }
6416 }
6417 }
6418
6419 static void collect_subscreen_tiles(SubscrPage& page, TileMoveList& list)
6420 {
6421 for(auto q = 0; q < page.contents.size(); ++q)
6422 {
6423 size_t indx = list.move_refs.size();
6424 collect_subscreen_tiles(*page.contents[q], list);
6425 for(; indx < list.move_refs.size(); ++indx)
6426 {
6427 auto& ref = list.move_refs[indx];
6428 ref->name = fmt::format("Widget {} - {}", q, ref->name);
6429 }
6430 }
6431 }
6432
6433 static void collect_subscreen_tiles(ZCSubscreen& subscreen, TileMoveList& list)
6434 {
6435 for (auto q = 0; q < subscreen.pages.size(); ++q)
6436 {
6437 size_t indx = list.move_refs.size();
6438 collect_subscreen_tiles(subscreen.pages[q], list);
6439 for(; indx < list.move_refs.size(); ++indx)
6440 {
6441 auto& ref = list.move_refs[indx];
6442 ref->name = fmt::format("Page {} - {}", q, ref->name);
6443 }
6444 }
6445 }
6446
6447 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6448 {
6449 bool BSZ2 = get_qr(qr_BSZELDA);
6450 bool move = source_process.has_value();
6451 TileMoveUndo local_undo;
6452 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6453 auto& vec = storage.vec;
6454 storage.diff = diff;
6455 storage.state = false;
6456
6457 //Combos
6458 {
6459 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6460 dest_process, source_process, mode,
6461 move
6462 ? "The tiles used by the following combos will be partially cleared by the move."
6463 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6464 ));
6465 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6466 {
6467 auto& cmb = combobuf[q];
6468 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6469 : fmt::format(" ({})", cmb.label));
6470 movelist->add_combo(&cmb, lbl);
6471
6472 //type-specific
6473 char const* type_name = ZI.getComboTypeName(cmb.type);
6474 switch(cmb.type)
6475 {
6476 case cSPOTLIGHT:
6477 {
6478 if(!(cmb.usrflags & cflag1))
6479 break;
6480 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6481 break;
6482 }
6483 }
6484 }
6485 if(!every_proc && !movelist->check_prot())
6486 return false;
6487 }
6488 //Items
6489 {
6490 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6491 dest_process, source_process, mode,
6492 move
6493 ? "The tiles used by the following items will be partially cleared by the move."
6494 : "The tiles used by the following items will be partially or completely overwritten by this process."
6495 ));
6496 build_bii_list(false);
6497 for(int32_t u=0; u<MAXITEMS; u++)
6498 {
6499 auto id = bii[u].i;
6500 itemdata& itm = itemsbuf[id];
6501 if(itm.family == itype_bottle)
6502 {
6503 vector<std::tuple<int,int,int>> rects;
6504 auto fr = itm.frames;
6505 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6506 {
6507 bottletype const& bt = QMisc.bottle_types[q];
6508 if(bt.is_blank())
6509 continue;
6510 rects.emplace_back(fr+q*fr, fr, 1);
6511 }
6512 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6513 false, 0, 0, rects);
6514 }
6515 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6516 }
6517 if(!every_proc && !movelist->check_prot())
6518 return false;
6519 }
6520 //Weapon sprites
6521 {
6522 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6523 dest_process, source_process, mode,
6524 move
6525 ? "The tiles used by the following weapons will be partially cleared by the move."
6526 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6527 ));
6528 build_biw_list();
6529
6530 for(int32_t u=0; u<MAXWPNS; u++)
6531 {
6532 bool ignore_frames=false;
6533 int32_t m=0;
6534
6535 auto id = biw[u].i;
6536 auto& wpn = wpnsbuf[id];
6537
6538 switch(biw[u].i)
6539 {
6540 case wSWORD:
6541 case wWSWORD:
6542 case wMSWORD:
6543 case wXSWORD:
6544 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6545 break;
6546
6547 case wSWORDSLASH:
6548 case wWSWORDSLASH:
6549 case wMSWORDSLASH:
6550 case wXSWORDSLASH:
6551 m=4;
6552 break;
6553
6554 case iwMMeter:
6555 m=9;
6556 break;
6557
6558 case wBRANG:
6559 case wMBRANG:
6560 case wFBRANG:
6561 m=BSZ2?1:3;
6562 break;
6563
6564 case wBOOM:
6565 case wSBOOM:
6566 case ewBOOM:
6567 case ewSBOOM:
6568 ignore_frames=true;
6569 m=2;
6570 break;
6571
6572 case wWAND:
6573 m=1;
6574 break;
6575
6576 case wMAGIC:
6577 m=1;
6578 break;
6579
6580 case wARROW:
6581 case wSARROW:
6582 case wGARROW:
6583 case ewARROW:
6584 m=1;
6585 break;
6586
6587 case wHAMMER:
6588 m=8;
6589 break;
6590
6591 case wHSHEAD:
6592 m=1;
6593 break;
6594
6595 case wHSCHAIN_H:
6596 m=1;
6597 break;
6598
6599 case wHSCHAIN_V:
6600 m=1;
6601 break;
6602
6603 case wHSHANDLE:
6604 m=1;
6605 break;
6606
6607 case iwDeath:
6608 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6609 {
6610 ignore_frames = true;
6611 m=BSZ2?4:2;
6612 }
6613 break;
6614
6615 case iwSpawn:
6616 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6617 {
6618 ignore_frames = true;
6619 m=3;
6620 }
6621 break;
6622 }
6623
6624 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6625 1, fmt::format("{} {}", biw[u].s, id));
6626
6627 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6628 //...these can't be updated by a move.
6629 if((u==3)||(u==9))
6630 {
6631 static int32_t impact_tiles[2] = {54,54};
6632 auto& tile = impact_tiles[u==3 ? 0 : 1];
6633 tile = 54; //dummy tile, ensure it's correct
6634 movelist->add_tile(&tile, 2, 1,
6635 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6636 true);
6637 }
6638 }
6639 if(!every_proc && !movelist->check_prot())
6640 return false;
6641 }
6642 //Hero sprites
6643 {
6644 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6645 dest_process, source_process, mode,
6646 move
6647 ? "The tiles used by the following Hero sprites will be partially cleared by the move."
6648 : "The tiles used by the following Hero sprites will be partially or completely overwritten by this process."
6649 ));
6650 {
6651 int32_t a_style=(zinit.heroAnimationStyle);
6652 #define ADD_HERO_SPRITE(ref_sprite, frames, name) \
6653 do \
6654 { \
6655 movelist->add_tile(&ref_sprite[spr_tile], \
6656 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6657 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6658 name, false, \
6659 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6660 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6661 } while(false)
6662 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6663
6664 for(int32_t i=0; i<4; ++i)
6665 {
6666 ADD_HERO_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6667 }
6668
6669 for(int32_t i=0; i<4; ++i)
6670 {
6671 ADD_HERO_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6672 }
6673
6674 for(int32_t i=0; i<4; ++i)
6675 {
6676 ADD_HERO_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6677 }
6678
6679 for(int32_t i=0; i<4; ++i)
6680 {
6681 ADD_HERO_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6682 }
6683
6684 for(int32_t i=0; i<2; ++i)
6685 {
6686 ADD_HERO_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6687 }
6688
6689 ADD_HERO_SPRITE(castingspr, 1, "Casting");
6690
6691 for(int32_t i=0; i<4; ++i)
6692 {
6693 ADD_HERO_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6694 }
6695
6696 for(int32_t i=0; i<4; ++i)
6697 {
6698 ADD_HERO_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6699 }
6700
6701 for(int32_t i=0; i<4; ++i)
6702 {
6703 ADD_HERO_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6704 }
6705
6706 for(int32_t i=0; i<2; ++i)
6707 {
6708 ADD_HERO_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6709 }
6710
6711 for(int32_t i=0; i<4; ++i)
6712 {
6713 ADD_HERO_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6714 }
6715
6716 for(int32_t i=0; i<4; ++i)
6717 {
6718 ADD_HERO_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6719 }
6720 for(int32_t i=0; i<4; ++i)
6721 {
6722 ADD_HERO_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6723 }
6724 for(int32_t i=0; i<4; ++i)
6725 {
6726 ADD_HERO_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6727 }
6728 for(int32_t i=0; i<4; ++i)
6729 {
6730 ADD_HERO_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6731 }
6732 for(int32_t i=0; i<4; ++i)
6733 {
6734 ADD_HERO_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6735 }
6736 for(int32_t i=0; i<4; ++i)
6737 {
6738 ADD_HERO_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6739 }
6740 for(int32_t i=0; i<4; ++i)
6741 {
6742 ADD_HERO_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6743 }
6744 for(int32_t i=0; i<4; ++i)
6745 {
6746 ADD_HERO_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6747 }
6748 //69
6749 for(int32_t i=0; i<4; ++i)
6750 {
6751 ADD_HERO_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6752 }
6753 //73
6754 for(int32_t i=0; i<4; ++i)
6755 {
6756 ADD_HERO_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6757 }
6758 //77
6759 for(int32_t i=0; i<4; ++i)
6760 {
6761 ADD_HERO_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6762 }
6763 //81
6764 for(int32_t i=0; i<4; ++i)
6765 {
6766 ADD_HERO_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6767 }
6768 //85
6769 ADD_HERO_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6770 ADD_HERO_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6771 ADD_HERO_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6772 for(int32_t i=0; i<4; ++i)
6773 {
6774 ADD_HERO_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6775 }
6776 //91
6777 }
6778 if(!every_proc && !movelist->check_prot())
6779 return false;
6780 }
6781 //Map Styles
6782 {
6783 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6784 dest_process, source_process, mode,
6785 move
6786 ? "The tiles used by the following map styles will be partially cleared by the move."
6787 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6788 ));
6789 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6790 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6791 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6792 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6793 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6794 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6795 if(!every_proc && !movelist->check_prot())
6796 return false;
6797 }
6798 //Game Icons
6799 {
6800 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6801 dest_process, source_process, mode,
6802 move
6803 ? "The tiles used by the following game icons will be partially cleared by the move."
6804 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6805 ));
6806 for(int32_t u=0; u<4; u++)
6807 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6808 if(!every_proc && !movelist->check_prot())
6809 return false;
6810 }
6811 //DMaps
6812 {
6813 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6814 dest_process, source_process, mode,
6815 move
6816 ? "The tiles used by the following dmaps will be partially cleared by the move."
6817 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6818 ));
6819 for(int32_t u=0; u<MAXDMAPS; u++)
6820 {
6821 auto& dm = DMaps[u];
6822 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6823 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6824 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6825 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6826 }
6827 if(!every_proc && !movelist->check_prot())
6828 return false;
6829 }
6830 //Enemies
6831 {
6832 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6833 dest_process, source_process, mode,
6834 move
6835 ? "The tiles used by the following enemies will be partially cleared by the move."
6836 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6837 ));
6838 build_bie_list(false);
6839 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6840 for(int u=0; u<eMAXGUYS; u++)
6841 {
6842 guydata& enemy=guysbuf[bie[u].i];
6843 bool darknut=false;
6844 bool gleeok=false;
6845
6846 if(enemy.family==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6847 darknut=true;
6848 else if(enemy.family==eeGLEEOK)
6849 gleeok=true;
6850 else if (enemy.family == eePATRA)
6851 {
6852 if (!get_qr(qr_PATRAS_USE_HARDCODED_OFFSETS))
6853 {
6854 darknut=true; //uses the same logic no need for separate variables!
6855 }
6856 }
6857
6858 // Dummied out enemies
6859 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6860 {
6861 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6862 {
6863 continue;
6864 }
6865 }
6866
6867 if(newtiles)
6868 {
6869 if(enemy.e_tile==0)
6870 {
6871 continue;
6872 }
6873
6874 vector<std::tuple<int,int,int>> rects;
6875
6876 if(darknut) //or anything that uses S. Tile for with new tiles
6877 {
6878 if (enemy.s_tile != 0)
6879 {
6880 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6881 }
6882 }
6883 else if (gleeok)
6884 {
6885 for (int32_t j = 0; j < enemy.attributes[4]; ++j)
6886 {
6887 rects.emplace_back(enemy.attributes[5] + (enemy.attributes[6]*j), 4, 1);
6888 }
6889 rects.emplace_back(enemy.attributes[7], 4, 1);
6890 rects.emplace_back(enemy.attributes[8], 4, 1);
6891 }
6892 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6893 false, 0, 0, rects);
6894
6895 }
6896 else
6897 {
6898 if(enemy.tile==0)
6899 {
6900 continue;
6901 }
6902 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6903
6904 if(enemy.s_tile!=0)
6905 {
6906 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6907 }
6908 }
6909 }
6910 if(!every_proc && !movelist->check_prot())
6911 return false;
6912 }
6913 //Subscreens
6914 {
6915 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6916 dest_process, source_process, mode,
6917 move
6918 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6919 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6920 ));
6921
6922 for(auto q = 0; q < subscreens_active.size(); ++q)
6923 {
6924 size_t indx = movelist->move_refs.size();
6925 collect_subscreen_tiles(subscreens_active[q], *movelist.get());
6926 for(; indx < movelist->move_refs.size(); ++indx)
6927 {
6928 auto& ref = movelist->move_refs[indx];
6929 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6930 }
6931 }
6932 for(auto q = 0; q < subscreens_passive.size(); ++q)
6933 {
6934 size_t indx = movelist->move_refs.size();
6935 collect_subscreen_tiles(subscreens_passive[q], *movelist.get());
6936 for(; indx < movelist->move_refs.size(); ++indx)
6937 {
6938 auto& ref = movelist->move_refs[indx];
6939 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6940 }
6941 }
6942 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6943 {
6944 size_t indx = movelist->move_refs.size();
6945 collect_subscreen_tiles(subscreens_overlay[q], *movelist.get());
6946 for(; indx < movelist->move_refs.size(); ++indx)
6947 {
6948 auto& ref = movelist->move_refs[indx];
6949 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6950 }
6951 }
6952 if(!every_proc && !movelist->check_prot())
6953 return false;
6954 }
6955 //Strings
6956 {
6957 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6958 dest_process, source_process, mode,
6959 move
6960 ? "The tiles used by the following strings will be partially cleared by the move."
6961 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6962 ));
6963 for(size_t q = 0; q < msg_count; ++q)
6964 {
6965 MsgStr& str = MsgStrings[q];
6966 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6967 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6968 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(str.s,100)));
6969 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6970 fmt::format("{} (Port.): '{}'", q, util::snip(str.s,100)));
6971 }
6972 if(!every_proc && !movelist->check_prot())
6973 return false;
6974 }
6975
6976 if(source_process) //Apply the 'diff' value to all moved tiles
6977 storage.redo();
6978 if(every_proc)
6979 for(auto &list : vec)
6980 for(auto &ref : list->move_refs)
6981 ref->forEach(every_proc);
6982 return true;
6983 }
6984 bool handle_tile_move(TileMoveProcess dest_process)
6985 {
6986 return _handle_tile_move(dest_process, nullopt, 0);
6987 }
6988 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6989 {
6990 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6991 }
6992 void for_every_used_tile(std::function<void(int32_t)> proc)
6993 {
6994 reset_combo_animations();
6995 reset_combo_animations2();
6996 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6997 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6998 }
6999
7000 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
7001 {
7002 bool BSZ2 = get_qr(qr_BSZELDA);
7003 bool move = source_process.has_value();
7004 ComboMoveUndo local_undo;
7005 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
7006 auto& vec = storage.vec;
7007 auto& combo_links = storage.combo_links;
7008 storage.diff = diff;
7009 storage.state = false;
7010 //Combo relative links
7011 {
7012 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7013 {
7014 newcombo& cmb = combobuf[q];
7015 if(cmb.trigchange)
7016 combo_links.add_to(q, q+cmb.trigchange);
7017 bool next = cmb.flag == mfSECRETSNEXT;
7018 switch(cmb.type)
7019 {
7020 case cPOUND:
7021 case cLOCKBLOCK: case cLOCKBLOCK2:
7022 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
7023 case cCHEST: case cCHEST2:
7024 case cLOCKEDCHEST: case cLOCKEDCHEST2:
7025 case cBOSSCHEST: case cBOSSCHEST2:
7026 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
7027 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
7028 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
7029 case cTALLGRASSNEXT: case cCRUMBLE:
7030 next = true;
7031 break;
7032 case cCSWITCH: case cCSWITCHBLOCK:
7033 combo_links.add_to(q, q+cmb.attributes[0]);
7034 break;
7035 case cLIGHTTARGET:
7036 if(cmb.usrflags & cflag1)
7037 combo_links.add_to(q, q-1);
7038 else next = true;
7039 break;
7040 case cSTEPSFX:
7041 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
7042 next = true;
7043 break;
7044 }
7045 if(next)
7046 combo_links.add_to(q, q+1);
7047 }
7048 }
7049
7050 //This function is expensive! Any optimizations possible should be made. -Em
7051
7052 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
7053 #define ADDC(ptr, str) \
7054 if(*ptr) movelist->add_combo(ptr, ComboProtection ? str : "");
7055 #define ADDC_10k(ptr, str) \
7056 if(*ptr) movelist->add_combo_10k(ptr, ComboProtection ? str : "");
7057 //Combos
7058 {
7059 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7060 combo_links, dest_process, source_process,
7061 move
7062 ? "The combos used by the following combos will be partially cleared by the move."
7063 : "The combos used by the following combos will be partially or completely overwritten by this process."
7064 ));
7065 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7066 {
7067 newcombo& cmb = combobuf[q];
7068 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
7069 : fmt::format(" ({})", cmb.label));
7070 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
7071 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
7072 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
7073 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
7074
7075 //type-specific
7076 char const* type_name = ZI.getComboTypeName(cmb.type);
7077 switch(cmb.type)
7078 {
7079 case cLOCKEDCHEST: case cBOSSCHEST:
7080 if(cmb.usrflags & cflag13)
7081 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7082 [[fallthrough]];
7083 case cCHEST:
7084 if(cmb.usrflags & cflag13)
7085 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7086 break;
7087 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7088 if(cmb.usrflags & cflag13)
7089 {
7090 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7091 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7092 }
7093 break;
7094 case cSIGNPOST:
7095 if(cmb.usrflags & cflag13)
7096 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7097 break;
7098 case cBUTTONPROMPT:
7099 if(cmb.usrflags & cflag13)
7100 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7101 break;
7102 }
7103 }
7104
7105 if(!movelist->check_prot())
7106 return false;
7107 }
7108 //Door Combo Sets
7109 {
7110 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7111 combo_links, dest_process, source_process,
7112 move
7113 ? "The combos used by the following screens will be partially cleared by the move."
7114 : "The combos used by the following screens will be partially or completely overwritten by this process."
7115 ));
7116 static const char* door_names[9] = {
7117 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7118 };
7119 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7120 {
7121 auto& dcs = DoorComboSets[i];
7122 auto& name = DoorComboSetNames[i];
7123 for(int32_t j=0; j<9; j++)
7124 {
7125 if(j<4)
7126 {
7127 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, name, j));
7128
7129 if(j<3)
7130 {
7131 if(j<2)
7132 {
7133 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, name, j));
7134 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, name, j));
7135 }
7136 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, name, j));
7137 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, name, j));
7138 }
7139 }
7140
7141 for(int32_t k=0; k<6; k++)
7142 {
7143 if(k<4)
7144 {
7145 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, name, door_names[j], k));
7146 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, name, door_names[j], k));
7147 }
7148
7149 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, name, door_names[j], k));
7150 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, name, door_names[j], k));
7151 }
7152 }
7153 }
7154
7155 if(!movelist->check_prot())
7156 return false;
7157 }
7158 //Combo Pools
7159 {
7160 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7161 combo_links, dest_process, source_process,
7162 move
7163 ? "The combos used by the following combo pools will be partially cleared by the move."
7164 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7165 ));
7166 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7167 {
7168 combo_pool& pool = combo_pools[q];
7169 int idx = 0;
7170 for(cpool_entry& cp : pool.combos)
7171 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7172 }
7173
7174 if(!movelist->check_prot())
7175 return false;
7176 }
7177 //Auto Combos
7178 {
7179 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7180 combo_links, dest_process, source_process,
7181 move
7182 ? "The combos used by the following autocombos will be partially cleared by the move."
7183 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7184 ));
7185 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7186 {
7187 combo_auto& cauto = combo_autos[q];
7188 int idx = 0;
7189 for (autocombo_entry& ac : cauto.combos)
7190 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7191 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7192 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7193 }
7194
7195 if(!movelist->check_prot())
7196 return false;
7197 }
7198 //Combo Aliases
7199 {
7200 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7201 combo_links, dest_process, source_process,
7202 move
7203 ? "The combos used by the following aliases will be partially cleared by the move."
7204 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7205 ));
7206 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7207 {
7208 //dimensions are 1 less than you would expect -DD
7209 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7210
7211 for(int32_t j=0; j<count; j++)
7212 {
7213 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7214 }
7215 }
7216
7217 if(!movelist->check_prot())
7218 return false;
7219 }
7220 //Favorite Combos
7221 {
7222 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7223 combo_links, dest_process, source_process,
7224 move
7225 ? "The combos used by the following favorite combos will be partially cleared by the move."
7226 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7227 ));
7228 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7229 {
7230 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7231 continue;
7232 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7233 }
7234
7235 if(!movelist->check_prot())
7236 return false;
7237 }
7238 //Bottle Shops
7239 {
7240 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7241 combo_links, dest_process, source_process,
7242 move
7243 ? "The combos used by the following bottle shops will be partially cleared by the move."
7244 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7245 ));
7246 for(auto q = 0; q < 256; ++q)
7247 for(auto p = 0; p < 3; ++p)
7248 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7249
7250 if(!movelist->check_prot())
7251 return false;
7252 }
7253 //Screens //EXPENSIVE! DO THIS LAST!
7254 {
7255 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7256 combo_links, dest_process, source_process,
7257 move
7258 ? "The combos used by the following screens will be partially cleared by the move."
7259 : "The combos used by the following screens will be partially or completely overwritten by this process."
7260 ));
7261
7262 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7263 {
7264 for(int32_t j=0; j<MAPSCRS; j++)
7265 {
7266 mapscr& scr = TheMaps[i*MAPSCRS+j];
7267
7268 if(!(scr.valid&mVALID))
7269 continue;
7270
7271 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7272
7273 // Specifying the exact position is too expensive - too much string creation.
7274 std::string data_str = ComboProtection ? fmt::format("{}x{:02X} - Combo", i, j) : "";
7275 for(int32_t k=0; k<176; k++)
7276 ADDC(&scr.data[k], data_str);
7277
7278 for(int32_t k=0; k<128; k++)
7279 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7280
7281 word maxffc = scr.numFFC();
7282 for(word k=0; k<maxffc; k++)
7283 {
7284 ffcdata& ffc = scr.ffcs[k];
7285 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7286 }
7287 }
7288 }
7289
7290 if(!movelist->check_prot())
7291 return false;
7292 }
7293 if(source_process) //Apply the 'diff' value to all moved combos
7294 storage.redo();
7295 return true;
7296 }
7297
7298 bool handle_combo_move(ComboMoveProcess dest_process)
7299 {
7300 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7301 }
7302 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7303 {
7304 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7305 }
7306 void register_used_tiles()
7307 {
7308 memset(used_tile_table, 0, sizeof(used_tile_table));
7309 for_every_used_tile([&](int tile)
7310 {
7311 used_tile_table[tile] = true;
7312 });
7313 }
7314
7315 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7316 {
7317 bool ctrl=(CHECK_CTRL_CMD);
7318 bool copied=false;
7319 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7320
7321 if(copied)
7322 {
7323 saved=false;
7324 }
7325
7326 return copied;
7327 }
7328
7329 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7330 {
7331 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7332 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7333
7334 // if tile>tile2 then swap them
7335 if(tile>tile2)
7336 {
7337 zc_swap(tile, tile2);
7338 }
7339
7340 // alt=copy from right
7341 // shift=copy from bottom
7342
7343 int32_t copies=copycnt;
7344 int32_t dest_first=tile;
7345 int32_t dest_last=tile2;
7346 int32_t src_first=copy;
7347 int32_t src_last=copy+copies-1;
7348
7349 int32_t dest_top=0;
7350 int32_t dest_bottom=0;
7351 int32_t src_top=0;
7352 int32_t src_bottom=0;
7353 int32_t src_left=0, src_right=0;
7354 int32_t src_width=0, src_height=0;
7355 int32_t dest_left=0, dest_right=0;
7356 int32_t dest_width=0, dest_height=0;
7357 int32_t rows=0, cols=0;
7358
7359 if(rect)
7360 {
7361 dest_top=TILEROW(dest_first);
7362 dest_bottom=TILEROW(dest_last);
7363 src_top=TILEROW(src_first);
7364 src_bottom=TILEROW(src_last);
7365
7366 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7367 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7368 src_first=(src_top * TILES_PER_ROW)+src_left;
7369 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7370
7371 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7372 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7373 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7374 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7375
7376 //if no dest range set, then set one
7377 if((dest_first==dest_last)&&(src_first!=src_last))
7378 {
7379 if(alt)
7380 {
7381 dest_left=dest_right-(src_right-src_left);
7382 }
7383 else
7384 {
7385 dest_right=dest_left+(src_right-src_left);
7386 }
7387
7388 if(shift)
7389 {
7390 dest_top=dest_bottom-(src_bottom-src_top);
7391 }
7392 else
7393 {
7394 dest_bottom=dest_top+(src_bottom-src_top);
7395 }
7396
7397 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7398 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7399 }
7400 else
7401 {
7402 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7403 {
7404 if(alt) //copy from right tile instead of left
7405 {
7406 src_left=src_right-(dest_right-dest_left);
7407 }
7408 else //copy from left tile
7409 {
7410 src_right=src_left+(dest_right-dest_left);
7411 }
7412 }
7413 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7414 {
7415 if(alt) //copy from right tile instead of left
7416 {
7417 dest_left=dest_right-(src_right-src_left);
7418 }
7419 else //copy from left tile
7420 {
7421 dest_right=dest_left+(src_right-src_left);
7422 }
7423 }
7424
7425 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7426 {
7427 if(shift) //copy from bottom tile instead of top
7428 {
7429 src_top=src_bottom-(dest_bottom-dest_top);
7430 }
7431 else //copy from top tile
7432 {
7433 src_bottom=src_top+(dest_bottom-dest_top);
7434 }
7435 }
7436 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7437 {
7438 if(shift) //copy from bottom tile instead of top
7439 {
7440 dest_top=dest_bottom-(src_bottom-src_top);
7441 }
7442 else //copy from top tile
7443 {
7444 dest_bottom=dest_top+(src_bottom-src_top);
7445 }
7446 }
7447
7448 src_first=(src_top * TILES_PER_ROW)+src_left;
7449 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7450 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7451 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7452 }
7453
7454 cols=src_right-src_left+1;
7455 rows=src_bottom-src_top+1;
7456
7457 dest_width=dest_right-dest_left+1;
7458 dest_height=dest_bottom-dest_top+1;
7459 src_width=src_right-src_left+1;
7460 src_height=src_bottom-src_top+1;
7461
7462 }
7463 else //!rect
7464 {
7465 //if no dest range set, then set one
7466 if((dest_first==dest_last)&&(src_first!=src_last))
7467 {
7468 if(alt)
7469 {
7470 dest_first=dest_last-(src_last-src_first);
7471 }
7472 else
7473 {
7474 dest_last=dest_first+(src_last-src_first);
7475 }
7476 }
7477 else
7478 {
7479 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7480 {
7481 if(alt) //copy from last tile instead of first
7482 {
7483 src_first=src_last-(dest_last-dest_first);
7484 }
7485 else //copy from first tile
7486 {
7487 src_last=src_first+(dest_last-dest_first);
7488 }
7489 }
7490 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7491 {
7492 if(alt) //copy from last tile instead of first
7493 {
7494 dest_first=dest_last-(src_last-src_first);
7495 }
7496 else //copy from first tile
7497 {
7498 dest_last=dest_first+(src_last-src_first);
7499 }
7500 }
7501 }
7502
7503 copies=dest_last-dest_first+1;
7504 }
7505
7506
7507
7508 char buf2[80], buf3[80], buf4[80];
7509 sprintf(buf2, " ");
7510 sprintf(buf3, " ");
7511 sprintf(buf4, " ");
7512
7513 // warn if range extends beyond last tile
7514 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7515
7516 if(dest_last>=NEWMAXTILES)
7517 {
7518 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7519 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7520 return false;
7521 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7522 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7523 // {
7524 // return false;
7525 // }
7526 }
7527
7528
7529 TileMoveUndo on_undo;
7530 // Overwrite warnings
7531 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7532 if(move)
7533 {
7534 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7535 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7536 return false;
7537 }
7538 else
7539 {
7540 if(!handle_tile_move(dest))
7541 return false;
7542 }
7543 // copy tiles and delete if needed (move)
7544
7545 {
7546 go_tiles();
7547
7548 int32_t diff=dest_first-src_first;
7549
7550 if(rect)
7551 {
7552 for(int32_t r=0; r<rows; ++r)
7553 {
7554 for(int32_t c=0; c<cols; ++c)
7555 {
7556 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7557 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7558
7559 if(dt>=NEWMAXTILES)
7560 continue;
7561
7562 overlay_tile(newtilebuf,dt,st,cs,backwards);
7563
7564 }
7565 }
7566 }
7567 else
7568 {
7569 for(int32_t c=0; c<copies; ++c)
7570 {
7571 int32_t dt=(dest_first+c);
7572 int32_t st=(src_first+c);
7573
7574 if(dt>=NEWMAXTILES)
7575 continue;
7576
7577 overlay_tile(newtilebuf,dt,st,cs,backwards);
7578
7579 if(move)
7580 {
7581 if(st<dest_first||st>(dest_first+c-1))
7582 reset_tile(newtilebuf, st, tf4Bit);
7583 }
7584 }
7585 }
7586 }
7587
7588 //now that tiles have moved, fix these buffers -DD
7589 register_blank_tiles();
7590 register_used_tiles();
7591
7592 if(move)
7593 last_tile_move_list = std::move(on_undo);
7594 return true;
7595 }
7596 //
7597 bool do_movetile_united(tile_move_data const& tmd)
7598 {
7599 char buf2[80], buf3[80], buf4[80];
7600 sprintf(buf2, " ");
7601 sprintf(buf3, " ");
7602 sprintf(buf4, " ");
7603
7604 // warn if range extends beyond last tile
7605 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7606
7607 if(tmd.dest_last>=NEWMAXTILES)
7608 {
7609 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7610 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7611 return false;
7612 }
7613
7614 TileMoveUndo on_undo;
7615 // Overwrite warnings
7616 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7617 if(tmd.move)
7618 {
7619 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7620 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7621 return false;
7622 }
7623 else
7624 {
7625 if(!handle_tile_move(dest))
7626 return false;
7627 }
7628
7629 // copy tiles and delete if needed (tmd.move)
7630 {
7631 go_tiles();
7632
7633 if(tmd.rect)
7634 {
7635 for(int32_t r=0; r<tmd.rows; ++r)
7636 {
7637 for(int32_t c=0; c<tmd.cols; ++c)
7638 {
7639 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7640 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7641
7642 if(dt>=NEWMAXTILES)
7643 continue;
7644
7645 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7646
7647 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7648 {
7649 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7650 }
7651
7652 if(tmd.move)
7653 {
7654 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7655 reset_tile(newtilebuf, st, tf4Bit);
7656 else
7657 {
7658 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7659 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7660 if(destLeft<=destRight)
7661 {
7662 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7663 reset_tile(newtilebuf, st, tf4Bit);
7664 }
7665 else // Wrapped around
7666 {
7667 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7668 reset_tile(newtilebuf, st, tf4Bit);
7669 }
7670 }
7671 }
7672 }
7673 }
7674 }
7675 else
7676 {
7677 for(int32_t c=0; c<tmd.copies; ++c)
7678 {
7679 int32_t dt=(tmd.dest_first+c);
7680 int32_t st=(tmd.src_first+c);
7681
7682 if(dt>=NEWMAXTILES)
7683 continue;
7684
7685 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7686
7687 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7688 {
7689 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7690 }
7691
7692 if(tmd.move)
7693 {
7694 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7695 reset_tile(newtilebuf, st, tf4Bit);
7696 }
7697 }
7698 }
7699 }
7700
7701 //now that tiles have moved, fix these buffers -DD
7702 register_blank_tiles();
7703 register_used_tiles();
7704
7705 if(tmd.move)
7706 last_tile_move_list = std::move(on_undo);
7707 return true;
7708 }
7709
7710 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7711 {
7712 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7713 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7714
7715 // if tile>tile2 then swap them
7716 if(tile>tile2)
7717 {
7718 zc_swap(tile, tile2);
7719 }
7720
7721 // alt=copy from right
7722 // shift=copy from bottom
7723 tile_move_data tmd;
7724
7725 tmd.copies=copycnt;
7726 tmd.dest_first=tile;
7727 tmd.dest_last=tile2;
7728 tmd.src_first=copy;
7729 tmd.src_last=copy+tmd.copies-1;
7730 tmd.rect = rect;
7731 tmd.move = move;
7732
7733 if(rect)
7734 {
7735 tmd.dest_top=TILEROW(tmd.dest_first);
7736 tmd.dest_bottom=TILEROW(tmd.dest_last);
7737 tmd.src_top=TILEROW(tmd.src_first);
7738 tmd.src_bottom=TILEROW(tmd.src_last);
7739
7740 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7741 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7742 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7743 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7744
7745 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7746 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7747 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7748 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7749
7750 //if no dest range set, then set one
7751 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7752 {
7753 if(alt)
7754 {
7755 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7756 }
7757 else
7758 {
7759 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7760 }
7761
7762 if(shift)
7763 {
7764 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7765 }
7766 else
7767 {
7768 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7769 }
7770
7771 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7772 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7773 }
7774 else
7775 {
7776 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7777 {
7778 if(alt) //copy from right tile instead of left
7779 {
7780 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7781 }
7782 else //copy from left tile
7783 {
7784 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7785 }
7786 }
7787 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7788 {
7789 if(alt) //copy from right tile instead of left
7790 {
7791 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7792 }
7793 else //copy from left tile
7794 {
7795 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7796 }
7797 }
7798
7799 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7800 {
7801 if(shift) //copy from bottom tile instead of top
7802 {
7803 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7804 }
7805 else //copy from top tile
7806 {
7807 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7808 }
7809 }
7810 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7811 {
7812 if(shift) //copy from bottom tile instead of top
7813 {
7814 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7815 }
7816 else //copy from top tile
7817 {
7818 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7819 }
7820 }
7821
7822 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7823 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7824 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7825 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7826 }
7827
7828 tmd.cols=tmd.src_right-tmd.src_left+1;
7829 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7830
7831 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7832 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7833 tmd.src_width=tmd.src_right-tmd.src_left+1;
7834 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7835
7836 }
7837 else //!rect
7838 {
7839 //if no dest range set, then set one
7840 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7841 {
7842 if(alt)
7843 {
7844 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7845 }
7846 else
7847 {
7848 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7849 }
7850 }
7851 else
7852 {
7853 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7854 {
7855 if(alt) //copy from last tile instead of first
7856 {
7857 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7858 }
7859 else //copy from first tile
7860 {
7861 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7862 }
7863 }
7864 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7865 {
7866 if(alt) //copy from last tile instead of first
7867 {
7868 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7869 }
7870 else //copy from first tile
7871 {
7872 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7873 }
7874 }
7875 }
7876
7877 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7878 }
7879
7880 return do_movetile_united(tmd);
7881 }
7882
7883 //
7884
7885 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7886 {
7887 assert(!move); //not implemented
7888
7889 // if tile>tile2 then swap them
7890 if(tile>tile2)
7891 {
7892 zc_swap(tile, tile2);
7893 }
7894
7895 tile_move_data tmd;
7896 tmd.copies=copycnt;
7897 tmd.dest_first=tile;
7898 tmd.dest_last=tile2;
7899 tmd.src_first=copy;
7900 tmd.src_last=copy+tmd.copies-1;
7901
7902
7903
7904 if(rect)
7905 {
7906 tmd.dest_top=TILEROW(tmd.dest_first);
7907 tmd.dest_bottom=TILEROW(tmd.dest_last);
7908 //tmd.src_top=TILEROW(tmd.src_first);
7909 //tmd.src_bottom=TILEROW(tmd.src_last);
7910
7911 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7912 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7913 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7914 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7915
7916 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7917 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7918 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7919 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7920
7921
7922
7923
7924 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7925 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7926
7927 tmd.cols=tmd.dest_width+1;
7928 tmd.rows=tmd.dest_height+1;
7929
7930 al_trace("tmd.rows: %d\n", tmd.rows);
7931 al_trace("tmd.cols: %d\n", tmd.cols);
7932
7933
7934 }
7935 else //!rect
7936 {
7937 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7938 }
7939
7940
7941
7942 char buf2[80], buf3[80], buf4[80];
7943 sprintf(buf2, " ");
7944 sprintf(buf3, " ");
7945 sprintf(buf4, " ");
7946
7947 // warn if range extends beyond last tile
7948 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7949
7950 if(tmd.dest_last>=NEWMAXTILES)
7951 {
7952 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7953 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7954 return false;
7955 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7956 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7957 // {
7958 // return false;
7959 // }
7960 }
7961
7962 TileMoveUndo on_undo;
7963 // Overwrite warnings
7964 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7965 if(tmd.move)
7966 {
7967 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7968 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7969 return false;
7970 }
7971 else
7972 {
7973 if(!handle_tile_move(dest))
7974 return false;
7975 }
7976
7977 // copy tiles and delete if needed (move)
7978
7979 {
7980 go_tiles();
7981
7982 int32_t diff=tmd.dest_first-tmd.src_first;
7983
7984 if(rect)
7985 {
7986 al_trace("floodfill, rect\n");
7987 al_trace("tmd.rows: %d\n", tmd.rows);
7988 al_trace("tmd.cols: %d\n", tmd.cols);
7989 for(int32_t r=0; r<tmd.rows; ++r)
7990 {
7991 for(int32_t c=0; c<tmd.cols; ++c)
7992 {
7993 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7994 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7995
7996 if(dt>=NEWMAXTILES)
7997 continue;
7998
7999 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8000
8001 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8002 {
8003 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8004 }
8005 }
8006 }
8007 }
8008 else
8009 {
8010 for(int32_t c=0; c<tmd.copies; ++c)
8011 {
8012 int32_t dt=(tmd.dest_first+c);
8013 int32_t st=(tmd.src_first+c);
8014
8015 if(dt>=NEWMAXTILES)
8016 continue;
8017
8018 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8019
8020 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8021 {
8022 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8023 }
8024
8025 }
8026 }
8027 }
8028
8029 //now that tiles have moved, fix these buffers -DD
8030 register_blank_tiles();
8031 register_used_tiles();
8032
8033 if(tmd.move)
8034 last_tile_move_list = std::move(on_undo);
8035 return true;
8036 }
8037 //
8038
8039 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8040 {
8041 al_trace("Floodfill Psste\n");
8042 bool ctrl=(CHECK_CTRL_CMD);
8043 bool copied=false;
8044 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
8045
8046 if(copied)
8047 {
8048 if(!ctrl)
8049 {
8050 copy=-1;
8051 tile2=tile;
8052 }
8053
8054 saved=false;
8055 }
8056
8057 return copied;
8058 }
8059
8060 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8061 {
8062 bool ctrl=(CHECK_CTRL_CMD);
8063 bool copied=false;
8064 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
8065
8066 if(copied)
8067 {
8068 if(!ctrl)
8069 {
8070 copy=-1;
8071 tile2=tile;
8072 }
8073
8074 saved=false;
8075 }
8076
8077 return copied;
8078 }
8079
8080 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
8081 {
8082 // if tile>tile2 then swap them
8083 if(tile>tile2)
8084 {
8085 zc_swap(tile, tile2);
8086 }
8087 int32_t src_top = TILEROW(tile);
8088 int32_t src_bottom = TILEROW(tile2);
8089 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8090 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8091 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8092 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8093
8094 int32_t src_width = src_right-src_left+1,
8095 src_height = src_bottom-src_top+1;
8096 int32_t dest_width = src_width, dest_height = src_height;
8097 zfix dest_rot = 0_zf;
8098 if(rotate)
8099 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8100 else
8101 ScaleTileDialog(&dest_width, &dest_height).show();
8102 if (rotate)
8103 {
8104 if (dest_rot == 0) return false;
8105 }
8106 else
8107 {
8108 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8109 }
8110 dest_width = vbound(dest_width, 1, 20);
8111 dest_height = vbound(dest_height, 1, 20);
8112
8113 int32_t dest_top = src_top;
8114 int32_t dest_bottom = src_top+dest_height-1;
8115 int32_t dest_left = src_left;
8116 int32_t dest_right = src_left+dest_width-1;
8117 int32_t dest_first = src_first;
8118 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8119
8120
8121 if(dest_last>=NEWMAXTILES)
8122 {
8123 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8124 return false;
8125 }
8126
8127 // Overwrite warnings
8128 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8129 return false;
8130
8131 //Do the rotate
8132 {
8133 go_tiles();
8134
8135 int32_t diff=dest_first-src_first;
8136 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8137 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8138 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8139 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8140 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8141 if (rotate)
8142 {
8143 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8144 }
8145 else
8146 {
8147 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8148 0, 0, destbmp->w, destbmp->h);
8149 }
8150 int32_t mhei = zc_max(src_height,dest_height),
8151 mwid = zc_max(src_width, dest_width);
8152 for(int32_t r=0; r<mhei; ++r)
8153 {
8154 for(int32_t c=0; c<mwid; ++c)
8155 {
8156 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8157
8158 if(dt>=NEWMAXTILES)
8159 continue;
8160 if(r < dest_height && c < dest_width)
8161 {
8162 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8163 }
8164 else reset_tile(newtilebuf, dt, tf4Bit);
8165 }
8166 }
8167 }
8168
8169 register_blank_tiles();
8170 register_used_tiles();
8171 return true;
8172 }
8173
8174 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8175 {
8176 //these 2 shouldn't be needed, but just to be safe...
8177 reset_combo_animations();
8178 reset_combo_animations2();
8179
8180 if(tile2<tile)
8181 {
8182 zc_swap(tile,tile2);
8183 }
8184
8185 auto first = tile;
8186 auto last = masscopy ? tile2 : first + copycnt-1;
8187 if(!handle_combo_move({first,last}))
8188 return;
8189
8190 if(!masscopy)
8191 {
8192 if(tile==copy)
8193 {
8194 copy=-1;
8195 tile2=tile;
8196 return;
8197 }
8198
8199 // go_combos(); // commented because caller does it for us
8200 //if copying to an earlier combo, copy from left to right
8201 //otherwise, copy from right to left
8202 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8203 {
8204 if(tile+t < MAXCOMBOS)
8205 {
8206 combobuf[tile+t]=combobuf[copy+t];
8207 }
8208 }
8209
8210 copy=-1;
8211 tile2=tile;
8212 saved=false;
8213 }
8214 else
8215 {
8216 // go_combos();
8217 int32_t src=copy, dest=tile;
8218
8219 do
8220 {
8221 combobuf[dest]=combobuf[src];
8222 ++src;
8223 ++dest;
8224
8225 if((src-copy)==copycnt) src=copy;
8226 }
8227 while(dest<=tile2);
8228
8229 copy=-1;
8230 tile2=tile;
8231 saved=false;
8232 }
8233
8234 setup_combo_animations();
8235 setup_combo_animations2();
8236 }
8237
8238 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8239 {
8240 reset_combo_animations();
8241 reset_combo_animations2();
8242 go_combos();
8243
8244 auto diff = cmd.tile - cmd.copy1;
8245 if(is_undoing)
8246 on_undo.undo();
8247 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8248 return false;
8249
8250 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8251 {
8252 if(cmd.tile+t < MAXCOMBOS)
8253 {
8254 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8255 clear_combo(cmd.copy1+t);
8256 }
8257 }
8258
8259 setup_combo_animations();
8260 setup_combo_animations2();
8261 saved=false;
8262 return true;
8263 }
8264
8265 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8266 {
8267 if(tile2<tile)
8268 {
8269 zc_swap(tile,tile2);
8270 }
8271
8272 if(tile==copy)
8273 {
8274 copy=-1;
8275 tile2=tile;
8276 return;
8277 }
8278
8279 combo_move_data cmd;
8280 cmd.tile = tile;
8281 cmd.tile2 = tile2;
8282 cmd.copy1 = copy;
8283 cmd.copycnt = copycnt;
8284
8285 ComboMoveUndo on_undo;
8286 if(!do_movecombo(cmd, on_undo))
8287 return;
8288 last_combo_move_list = std::move(on_undo);
8289 copy=-1;
8290 tile2=tile;
8291 }
8292
8293 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8294 {
8295 if(firsttile > lasttile)
8296 zc_swap(firsttile,lasttile);
8297 int32_t coldiff = 0;
8298 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8299 {
8300 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8301 firsttile-=coldiff;
8302 lasttile+=coldiff;
8303 }
8304 for(int32_t t=firsttile; t<=lasttile; ++t)
8305 if(!rect_sel ||
8306 ((TILECOL(t)>=TILECOL(firsttile)) &&
8307 (TILECOL(t)<=TILECOL(lasttile))))
8308 reset_tile(newtilebuf, t, tf4Bit);
8309 saved=false;
8310 register_blank_tiles();
8311 }
8312
8313 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8314 {
8315 char buf[40];
8316
8317 if(tile==tile2)
8318 {
8319 sprintf(buf,"Delete tile %d?",tile);
8320 }
8321 else
8322 {
8323 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8324 }
8325
8326 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8327 {
8328 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8329
8330 go_tiles();
8331
8332 //if copying to an earlier tile, copy from left to right
8333 //otherwise, copy from right to left
8334 do_delete_tiles(firsttile, lasttile, rect_sel);
8335
8336 tile=tile2=zc_min(tile,tile2);
8337 saved=false;
8338 register_blank_tiles();
8339 }
8340 }
8341
8342 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8343 {
8344 byte buf[256];
8345 go_tiles();
8346
8347 unpack_tile(newtilebuf, dest, 0, false);
8348
8349 for(int32_t i=0; i<256; i++)
8350 buf[i] = unpackbuf[i];
8351
8352 unpack_tile(newtilebuf, src, 0, false);
8353
8354 if(newtilebuf[src].format>tf4Bit)
8355 {
8356 cs=0;
8357 }
8358
8359 cs &= 15;
8360 cs <<= CSET_SHFT;
8361
8362 for(int32_t i=0; i<256; i++)
8363 {
8364 if(backwards)
8365 {
8366 if(!buf[i])
8367 {
8368 buf[i] = unpackbuf[i]+cs;
8369 }
8370 }
8371 else
8372 {
8373 if(unpackbuf[i])
8374 {
8375 buf[i] = unpackbuf[i]+cs;
8376 }
8377 }
8378 }
8379
8380 pack_tile(newtilebuf, buf,dest);
8381 saved=false;
8382 }
8383
8384 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8385 {
8386 //byte buf[256];
8387 go_tiles();
8388
8389 if(!rect_sel)
8390 {
8391 for(int32_t d=dest1; d <= dest2; ++d)
8392 {
8393 /*unpack_tile(newtilebuf, d, 0, false);
8394
8395 for(int32_t i=0; i<256; i++)
8396 {
8397 if(!backwards)
8398 {
8399 if(!buf[i])
8400 {
8401 buf[i] = unpackbuf[i] + cs;
8402 }
8403 }
8404 else
8405 {
8406 if(unpackbuf[i])
8407 {
8408 buf[i] = unpackbuf[i] + cs;
8409 }
8410 }
8411 }
8412
8413 pack_tile(newtilebuf, buf,d);
8414 */
8415
8416 overlay_tile(newtilebuf,d,src,cs,backwards);
8417
8418 if(!blank_tile_table[src])
8419 {
8420 blank_tile_table[d]=false;
8421 }
8422 }
8423 }
8424 else
8425 {
8426 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8427 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8428 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8429 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8430 int32_t d=0;
8431
8432 for(int32_t j=cmin; j<=cmax; ++j)
8433 {
8434 for(int32_t k=rmin; k<=rmax; ++k)
8435 {
8436 d=j+TILES_PER_ROW*k;
8437 /*unpack_tile(newtilebuf, d, 0, false);
8438
8439 for(int32_t i=0; i<256; i++)
8440 {
8441 if(!backwards)
8442 {
8443 if(!buf[i])
8444 {
8445 buf[i] = unpackbuf[i] + cs;
8446 }
8447 }
8448 else
8449 {
8450 if(unpackbuf[i])
8451 {
8452 buf[i] = unpackbuf[i] + cs;
8453 }
8454 }
8455 }
8456
8457 pack_tile(newtilebuf, buf,d);
8458 */
8459
8460 overlay_tile(newtilebuf,d,src,cs,backwards);
8461
8462 if(!blank_tile_table[src])
8463 {
8464 blank_tile_table[d]=false;
8465 }
8466 }
8467 }
8468 }
8469
8470 return;
8471 }
8472
8473 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8474 {
8475 tile+=s;
8476 bound(tile,0,NEWMAXTILES-1);
8477
8478 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8479 tile2 = tile;
8480
8481 first = tile - (tile%TILES_PER_PAGE);
8482 }
8483
8484 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8485 {
8486 int32_t cst;
8487
8488 switch(bp2)
8489 {
8490 case tf4Bit:
8491 switch(newtilebuf[t].format)
8492 {
8493 case tf4Bit:
8494 //already in the right format
8495 break;
8496
8497 case tf8Bit:
8498 unpack_tile(newtilebuf, t, 0, true);
8499
8500 if(alt) //reduce
8501 {
8502 for(int32_t i=0; i<256; i++)
8503 {
8504 if(!shift||unpackbuf[i]!=0)
8505 {
8506 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8507 }
8508 }
8509 }
8510 else //truncate
8511 {
8512 for(int32_t i=0; i<256; i++)
8513 {
8514 unpackbuf[i]&=15;
8515 }
8516 }
8517
8518 reset_tile(newtilebuf, t, tf4Bit);
8519 pack_tile(newtilebuf, unpackbuf, t);
8520 break;
8521 }
8522
8523 break;
8524
8525 case tf8Bit:
8526 switch(newtilebuf[t].format)
8527 {
8528 case tf4Bit:
8529 unpack_tile(newtilebuf, t, 0, true);
8530 cst = cs&15;
8531 cst <<= CSET_SHFT;
8532
8533 for(int32_t i=0; i<256; i++)
8534 {
8535 if(!shift||unpackbuf[i]!=0)
8536 {
8537 unpackbuf[i]+=cst;
8538 }
8539 }
8540
8541 reset_tile(newtilebuf, t, tf8Bit);
8542 pack_tile(newtilebuf, unpackbuf, t);
8543 break;
8544
8545 case tf8Bit:
8546 //already in the right format
8547 break;
8548 }
8549
8550 break;
8551 }
8552 }
8553
8554 static DIALOG create_relational_tiles_dlg[] =
8555 {
8556 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8557 12 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8558 12 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8559 12 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8560 12 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8561 12 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8562 12 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8563 12 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8564 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8565 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8566 };
8567
8568 void draw_tile_list_window()
8569 {
8570 int32_t w = 640;
8571 int32_t h = 480;
8572
8573 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8574 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8575 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8576 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8577
8578 FONT *oldfont = font;
8579 font = get_zc_font(font_lfont);
8580 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8581 font=oldfont;
8582 return;
8583 }
8584
8585 void show_blank_tile(int32_t t)
8586 {
8587 char tbuf[80], tbuf2[80], tbuf3[80];
8588 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8589 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8590 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8591 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8592 }
8593
8594 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8595 {
8596 int num_bits;
8597 if (format == tf4Bit)
8598 num_bits = 4;
8599 else if (format == tf8Bit)
8600 num_bits = 8;
8601 else assert(false);
8602
8603 char buf[80];
8604 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8605
8606 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8607 {
8608 go_tiles();
8609 saved=false;
8610
8611 if(format == tf4Bit)
8612 {
8613 memset(cset_reduce_table, 0, 256);
8614 memset(col_diff,0,3*128);
8615 calc_cset_reduce_table(RAMpal, cs);
8616 }
8617
8618 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8619
8620 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8621 {
8622 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8623 firsttile-=coldiff;
8624 lasttile+=coldiff;
8625 }
8626
8627 for(int32_t t=firsttile; t<=lasttile; t++)
8628 if(!rect_sel ||
8629 ((TILECOL(t)>=TILECOL(firsttile)) &&
8630 (TILECOL(t)<=TILECOL(lasttile))))
8631 convert_tile(t, format, cs, shift, alt);
8632
8633 tile=tile2=zc_min(tile,tile2);
8634 }
8635 }
8636
8637
8638 int32_t readtilefile(PACKFILE *f)
8639 {
8640 dword section_version=0;
8641 int32_t zversion = 0;
8642 int32_t zbuild = 0;
8643
8644 if(!p_igetl(&zversion,f))
8645 {
8646 return 0;
8647 }
8648 if(!p_igetl(&zbuild,f))
8649 {
8650 return 0;
8651 }
8652 if(!p_igetw(&section_version,f))
8653 {
8654 return 0;
8655 }
8656 if(!read_deprecated_section_cversion(f))
8657 {
8658 return 0;
8659 }
8660 al_trace("readoneweapon section_version: %d\n", section_version);
8661
8662 if ( zversion > ZELDA_VERSION )
8663 {
8664 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8665 return 0;
8666 }
8667
8668 else if ( ( section_version > V_TILES ))
8669 {
8670 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8671 return 0;
8672
8673 }
8674 else
8675 {
8676 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8677 }
8678
8679 int32_t index = 0;
8680 int32_t count = 0;
8681
8682 //tile id
8683 if(!p_igetl(&index,f))
8684 {
8685 return 0;
8686 }
8687 al_trace("Reading tile: index(%d)\n", index);
8688
8689 //tile count
8690 if(!p_igetl(&count,f))
8691 {
8692 return 0;
8693 }
8694 al_trace("Reading tile: count(%d)\n", count);
8695
8696
8697
8698
8699 for ( int32_t tilect = 0; tilect < count; tilect++ )
8700 {
8701 byte *temp_tile = new byte[tilesize(tf32Bit)];
8702 byte format=tf4Bit;
8703 memset(temp_tile, 0, tilesize(tf32Bit));
8704 if(!p_getc(&format,f))
8705 {
8706 delete[] temp_tile;
8707 return 0;
8708 }
8709
8710
8711 if(!pfread(temp_tile,tilesize(format),f))
8712 {
8713 delete[] temp_tile;
8714 return 0;
8715 }
8716
8717 reset_tile(newtilebuf, index+(tilect), format);
8718 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8719 delete[] temp_tile;
8720 }
8721
8722
8723 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8724
8725 register_blank_tiles();
8726 register_used_tiles();
8727
8728 return 1;
8729
8730 }
8731
8732 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8733 {
8734 dword section_version=0;
8735 int32_t zversion = 0;
8736 int32_t zbuild = 0;
8737
8738 if(!p_igetl(&zversion,f))
8739 {
8740 return 0;
8741 }
8742 if(!p_igetl(&zbuild,f))
8743 {
8744 return 0;
8745 }
8746 if(!p_igetw(&section_version,f))
8747 {
8748 return 0;
8749 }
8750 if(!read_deprecated_section_cversion(f))
8751 {
8752 return 0;
8753 }
8754 al_trace("readoneweapon section_version: %d\n", section_version);
8755
8756 if ( zversion > ZELDA_VERSION )
8757 {
8758 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8759 return 0;
8760 }
8761
8762 else if ( ( section_version > V_TILES ))
8763 {
8764 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8765 return 0;
8766
8767 }
8768 else
8769 {
8770 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8771 }
8772
8773 int32_t index = 0;
8774 int32_t count = 0;
8775
8776 //tile id
8777 if(!p_igetl(&index,f))
8778 {
8779 return 0;
8780 }
8781 al_trace("Reading tile: index(%d)\n", index);
8782
8783 //tile count
8784 if(!p_igetl(&count,f))
8785 {
8786 return 0;
8787 }
8788 al_trace("Reading tile: count(%d)\n", count);
8789
8790
8791 for ( int32_t tilect = 0; tilect < count; tilect++ )
8792 {
8793 byte *temp_tile = new byte[tilesize(tf32Bit)];
8794 byte format=tf4Bit;
8795 memset(temp_tile, 0, tilesize(tf32Bit));
8796 if(!p_getc(&format,f))
8797 {
8798 delete[] temp_tile;
8799 return 0;
8800 }
8801
8802
8803 if(!pfread(temp_tile,tilesize(format),f))
8804 {
8805 delete[] temp_tile;
8806 return 0;
8807 }
8808
8809 reset_tile(newtilebuf, start+(tilect), format);
8810 if ( skip )
8811 {
8812 if ( (start+(tilect)) < skip )
8813 {
8814 delete[] temp_tile;
8815 continue;
8816 }
8817
8818 }
8819 if ( start+(tilect) < NEWMAXTILES )
8820 {
8821 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8822 }
8823 delete[] temp_tile;
8824
8825 }
8826
8827
8828 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8829
8830 register_blank_tiles();
8831 register_used_tiles();
8832
8833 return 1;
8834
8835 }
8836
8837
8838 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8839 {
8840 dword section_version=0;
8841 int32_t zversion = 0;
8842 int32_t zbuild = 0;
8843
8844 if(!p_igetl(&zversion,f))
8845 {
8846 return 0;
8847 }
8848 if(!p_igetl(&zbuild,f))
8849 {
8850 return 0;
8851 }
8852 if(!p_igetw(&section_version,f))
8853 {
8854 return 0;
8855 }
8856 if(!read_deprecated_section_cversion(f))
8857 {
8858 return 0;
8859 }
8860 al_trace("readoneweapon section_version: %d\n", section_version);
8861
8862 if ( zversion > ZELDA_VERSION )
8863 {
8864 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8865 return 0;
8866 }
8867
8868 else if ( ( section_version > V_TILES ))
8869 {
8870 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8871 return 0;
8872
8873 }
8874 else
8875 {
8876 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8877 }
8878
8879 int32_t index = 0;
8880 int32_t count = 0;
8881
8882 //tile id
8883 if(!p_igetl(&index,f))
8884 {
8885 return 0;
8886 }
8887 al_trace("Reading tile: index(%d)\n", index);
8888
8889 //tile count
8890 if(!p_igetl(&count,f))
8891 {
8892 return 0;
8893 }
8894 al_trace("Reading tile: count(%d)\n", count);
8895
8896
8897
8898
8899 for ( int32_t tilect = 0; tilect < count; tilect++ )
8900 {
8901 byte *temp_tile = new byte[tilesize(tf32Bit)];
8902 byte format=tf4Bit;
8903 memset(temp_tile, 0, tilesize(tf32Bit));
8904
8905 if(!p_getc(&format,f))
8906 {
8907 delete[] temp_tile;
8908 return 0;
8909 }
8910
8911
8912 if(!pfread(temp_tile,tilesize(format),f))
8913 {
8914 delete[] temp_tile;
8915 return 0;
8916 }
8917
8918 reset_tile(newtilebuf, start+(tilect), format);
8919 if ( start+(tilect) < NEWMAXTILES )
8920 {
8921 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8922 }
8923 delete[] temp_tile;
8924 }
8925
8926
8927 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8928
8929 register_blank_tiles();
8930 register_used_tiles();
8931
8932 return 1;
8933
8934 }
8935 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8936 {
8937 dword section_version=V_TILES;
8938 int32_t zversion = ZELDA_VERSION;
8939 int32_t zbuild = VERSION_BUILD;
8940
8941 if(!p_iputl(zversion,f))
8942 {
8943 return 0;
8944 }
8945 if(!p_iputl(zbuild,f))
8946 {
8947 return 0;
8948 }
8949 if(!p_iputw(section_version,f))
8950 {
8951 return 0;
8952 }
8953
8954 if(!write_deprecated_section_cversion(section_version,f))
8955 {
8956 return 0;
8957 }
8958
8959 //start tile id
8960 if(!p_iputl(index,f))
8961 {
8962 return 0;
8963 }
8964
8965 //count
8966 if(!p_iputl(count,f))
8967 {
8968 return 0;
8969 }
8970
8971 for ( int32_t tilect = 0; tilect < count; tilect++ )
8972 {
8973 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8974 {
8975 return 0;
8976 }
8977 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8978 {
8979 return 0;
8980 }
8981 }
8982
8983 return 1;
8984
8985 }
8986
8987 static int32_t _selected_tile=-1, _selected_tcset=-1;
8988 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8989 {
8990 popup_zqdialog_start();
8991 reset_combo_animations();
8992 reset_combo_animations2();
8993 bound(tile,0,NEWMAXTILES-1);
8994 ex=exnow;
8995 int32_t done=0;
8996 int32_t oflip=flip;
8997 int32_t otile=tile;
8998 int32_t ocs=cs;
8999 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
9000 int32_t copy=-1;
9001 int32_t tile2=tile,copycnt=0;
9002 reftile = 0;
9003 int32_t tile_clicked=-1;
9004 bool rect_sel=true;
9005 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
9006 position_mouse_z(0);
9007
9008 go();
9009
9010 register_used_tiles();
9011 int32_t w = 640;
9012 int32_t h = 480;
9013 int32_t window_xofs=(zq_screen_w-w-12)>>1;
9014 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
9015 int32_t screen_xofs=window_xofs+6;
9016 int32_t screen_yofs=window_yofs+25;
9017 int32_t panel_yofs=3;
9018 int32_t mul = 2;
9019 FONT *tfont = get_zc_font(font_lfont_l);
9020
9021 draw_tile_list_window();
9022 int32_t f=0;
9023 draw_tiles(first,cs,f);
9024
9025 if(type==0)
9026 {
9027 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
9028 }
9029 else
9030 {
9031 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
9032 }
9033
9034 go_tiles();
9035
9036 while(gui_mouse_b())
9037 {
9038 /* do nothing */
9039 rest(1);
9040 }
9041
9042 bool bdown=false;
9043
9044 #define FOREACH_START(_t) \
9045 { \
9046 int32_t _first, _last; \
9047 if(is_rect) \
9048 { \
9049 _first=top*TILES_PER_ROW+left; \
9050 _last=_first+rows*TILES_PER_ROW|+columns-1; \
9051 } \
9052 else \
9053 { \
9054 _first=zc_min(tile, tile2); \
9055 _last=zc_max(tile, tile2); \
9056 } \
9057 for(int32_t _t=_first; _t<=_last; _t++) \
9058 { \
9059 if(is_rect) \
9060 { \
9061 int32_t row=TILEROW(_t); \
9062 if(row<top || row>=top+rows) \
9063 continue; \
9064 int32_t col=TILECOL(_t); \
9065 if(col<left || col>=left+columns) \
9066 continue; \
9067 } \
9068
9069 #define FOREACH_END\
9070 } \
9071 }
9072
9073 bool did_snap = false;
9074 int otl = tile, otl2 = tile2;
9075 do
9076 {
9077 HANDLE_CLOSE_ZQDLG();
9078 if(exiting_program) break;
9079 rest(4);
9080 int32_t top=TILEROW(zc_min(tile, tile2));
9081 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9082 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9083 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9084 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9085 bool redraw=false;
9086
9087 if(mouse_z!=0)
9088 {
9089 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9090 position_mouse_z(0);
9091 redraw=true;
9092 }
9093
9094 if(keypressed())
9095 {
9096 switch(readkey()>>8)
9097 {
9098 case KEY_ENTER_PAD:
9099 case KEY_ENTER:
9100 done=2;
9101 break;
9102
9103 case KEY_ESC:
9104 done=1;
9105 break;
9106
9107 case KEY_F1:
9108 onHelp();
9109 break;
9110
9111 case KEY_EQUALS:
9112 case KEY_PLUS_PAD:
9113 {
9114 if(CHECK_CTRL_CMD ||
9115 key[KEY_ALT] || key[KEY_ALTGR])
9116 {
9117 FOREACH_START(t)
9118 if(key[KEY_ALT] || key[KEY_ALTGR])
9119 shift_tile_colors(t, 16, false);
9120 else
9121 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9122 FOREACH_END
9123
9124 register_blank_tiles();
9125 }
9126 else if(edit_cs)
9127 cs = (cs<13) ? cs+1:0;
9128
9129 redraw=true;
9130 break;
9131 }
9132
9133 case KEY_Z:
9134 case KEY_F12:
9135 {
9136 if(!did_snap)
9137 {
9138 //Export tile page as screenshot
9139 PALETTE temppal;
9140 get_palette(temppal);
9141 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9142 draw_tiles(tempbmp,first,cs,f,false,true);
9143 save_bitmap(getSnapName(), tempbmp, RAMpal);
9144 destroy_bitmap(tempbmp);
9145
9146 redraw = true;
9147 did_snap = true;
9148 }
9149 break;
9150 }
9151
9152 case KEY_S:
9153 {
9154 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9155 break;
9156 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9157 if(!f) break;
9158 al_trace("Saving tile: %d\n", tile);
9159 writetilefile(f,tile,1);
9160 pack_fclose(f);
9161 break;
9162 }
9163 case KEY_L:
9164 {
9165 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9166 break;
9167 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9168 if(!f) break;
9169 al_trace("Saving tile: %d\n", tile);
9170 if (!readtilefile(f))
9171 {
9172 al_trace("Could not read from .ztile packfile %s\n", temppath);
9173 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9174 }
9175 else
9176 {
9177 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9178 }
9179
9180 pack_fclose(f);
9181 //register_blank_tiles();
9182 //register_used_tiles();
9183 redraw=true;
9184 break;
9185 }
9186 case KEY_MINUS:
9187 case KEY_MINUS_PAD:
9188 {
9189 if(CHECK_CTRL_CMD ||
9190 key[KEY_ALT] || key[KEY_ALTGR])
9191 {
9192 FOREACH_START(t)
9193 if(key[KEY_ALT] || key[KEY_ALTGR])
9194 shift_tile_colors(t, -16, false);
9195 else
9196 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9197 FOREACH_END
9198
9199 register_blank_tiles();
9200 }
9201 else if(edit_cs)
9202 cs = (cs>0) ? cs-1:13;
9203
9204 redraw=true;
9205 break;
9206 }
9207
9208 case KEY_UP:
9209 {
9210 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9211 {
9212 case 3: //ALT and CTRL
9213 case 2: //ALT
9214 if(is_rect)
9215 {
9216 saved=false;
9217 go_slide_tiles(columns, rows, top, left);
9218 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9219 bool same = true;
9220
9221 for(int32_t d=0; d<columns; d++)
9222 {
9223 for(int32_t s=0; s<rows; s++)
9224 {
9225 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9226
9227 if(newtilebuf[t].format!=bitcheck) same = false;
9228 }
9229 }
9230
9231 if(!same) break;
9232
9233 // This used to do something. Too lazy to remove.
9234 // Can probably remove the above "same" check too.
9235 bitcheck = 2;
9236
9237 for(int32_t c=0; c<columns; c++)
9238 {
9239 for(int32_t r=0; r<rows; r++)
9240 {
9241 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9242 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9243 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9244
9245 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9246 {
9247 if(pixelrow==15*bitcheck)
9248 {
9249 int32_t srctile=temptile+TILES_PER_ROW;
9250 if(srctile>=NEWMAXTILES)
9251 srctile-=rows*TILES_PER_ROW;
9252 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9253 }
9254
9255 *dest_pixelrow=*src_pixelrow;
9256 dest_pixelrow++;
9257 src_pixelrow++;
9258 }
9259 }
9260
9261 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9262
9263 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9264 {
9265 if((CHECK_CTRL_CMD))
9266 {
9267 *dest_pixelrow=0;
9268 }
9269 else
9270 {
9271 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9272 *dest_pixelrow=*src_pixelrow;
9273 }
9274 }
9275 }
9276 }
9277
9278 register_blank_tiles();
9279 redraw=true;
9280 break;
9281
9282 case 1: //CTRL
9283 case 0: //None
9284 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9285 redraw=true;
9286
9287 default: //Others
9288 break;
9289 }
9290 }
9291 break;
9292
9293 case KEY_DOWN:
9294 {
9295 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9296 {
9297 case 3: //ALT and CTRL
9298 case 2: //ALT
9299 if(is_rect)
9300 {
9301 saved=false;
9302 go_slide_tiles(columns, rows, top, left);
9303 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9304 bool same = true;
9305
9306 for(int32_t c=0; c<columns; c++)
9307 {
9308 for(int32_t r=0; r<rows; r++)
9309 {
9310 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9311
9312 if(newtilebuf[t].format!=bitcheck) same = false;
9313 }
9314 }
9315
9316 if(!same) break;
9317
9318 // This used to do something. Too lazy to remove.
9319 // Can probably remove the above "same" check too.
9320 bitcheck = 2;
9321
9322 for(int32_t c=0; c<columns; c++)
9323 {
9324 for(int32_t r=rows-1; r>=0; r--)
9325 {
9326 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9327 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9328 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9329
9330 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9331 {
9332 if(pixelrow<bitcheck)
9333 {
9334 int32_t srctile=temptile-TILES_PER_ROW;
9335 if(srctile<0)
9336 srctile+=rows*TILES_PER_ROW;
9337 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9338 *dest_pixelrow=*tempsrc;
9339 //*dest_pixelrow=0;
9340 }
9341 else
9342 {
9343 *dest_pixelrow=*src_pixelrow;
9344 }
9345
9346 dest_pixelrow--;
9347 src_pixelrow--;
9348 }
9349 }
9350
9351 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9352 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9353
9354 for(int32_t b=0; b<bitcheck; b++)
9355 {
9356 if((CHECK_CTRL_CMD))
9357 {
9358 *dest_pixelrow=0;
9359 }
9360 else
9361 {
9362 *dest_pixelrow=*src_pixelrow;
9363 }
9364
9365 dest_pixelrow++;
9366 src_pixelrow++;
9367 }
9368 }
9369 }
9370
9371 register_blank_tiles();
9372 redraw=true;
9373 break;
9374
9375 case 1: //CTRL
9376 case 0: //None
9377 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9378 redraw=true;
9379
9380 default: //Others
9381 break;
9382 }
9383 }
9384 break;
9385
9386 case KEY_LEFT:
9387 {
9388 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9389 {
9390 case 3: //ALT and CTRL
9391 case 2: //ALT
9392 if(is_rect)
9393 {
9394 saved=false;
9395 go_slide_tiles(columns, rows, top, left);
9396 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9397 bool same = true;
9398
9399 for(int32_t c=0; c<columns; c++)
9400 {
9401 for(int32_t r=0; r<rows; r++)
9402 {
9403 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9404
9405 if(newtilebuf[t].format!=bitcheck) same = false;
9406 }
9407 }
9408
9409 if(!same) break;
9410
9411 // This used to do something. Too lazy to remove.
9412 // Can probably remove the above "same" check too.
9413 bitcheck = 2;
9414
9415 for(int32_t r=0; r<rows; r++)
9416 {
9417 for(int32_t c=0; c<columns; c++)
9418 {
9419 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9420 byte *dest_pixelrow=(newtilebuf[temptile].data);
9421
9422 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9423 {
9424 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9425 {
9426 *dest_pixelrow=*(dest_pixelrow+1);
9427 dest_pixelrow++;
9428 }
9429
9430 if(c==columns-1)
9431 {
9432 if(!(CHECK_CTRL_CMD))
9433 {
9434 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9435 *dest_pixelrow=*tempsrc;
9436 }
9437 }
9438 else
9439
9440 {
9441 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9442 *dest_pixelrow=*tempsrc;
9443 }
9444
9445 dest_pixelrow++;
9446 }
9447 }
9448 }
9449
9450 register_blank_tiles();
9451 redraw=true;
9452 }
9453
9454 break;
9455
9456 case 1: //CTRL
9457 case 0: //None
9458 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9459 redraw=true;
9460
9461 default: //Others
9462 break;
9463 }
9464 }
9465 break;
9466
9467 case KEY_RIGHT:
9468 {
9469 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9470 {
9471 case 3: //ALT and CTRL
9472 case 2: //ALT
9473 if(is_rect)
9474 {
9475 saved=false;
9476 go_slide_tiles(columns, rows, top, left);
9477 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9478 bool same = true;
9479
9480 for(int32_t c=0; c<columns; c++)
9481 {
9482 for(int32_t r=0; r<rows; r++)
9483 {
9484 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9485
9486 if(newtilebuf[t].format!=bitcheck) same = false;
9487 }
9488 }
9489
9490 if(!same) break;
9491
9492 // This used to do something. Too lazy to remove.
9493 // Can probably remove the above "same" check too.
9494 bitcheck = 2;
9495
9496 for(int32_t r=0; r<rows; r++)
9497 {
9498 for(int32_t c=columns-1; c>=0; c--)
9499 {
9500 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9501 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9502
9503 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9504 {
9505 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9506 {
9507 *dest_pixelrow=*(dest_pixelrow-1);
9508 dest_pixelrow--;
9509 }
9510
9511 if(c==0)
9512 {
9513 if(!(CHECK_CTRL_CMD))
9514 {
9515 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9516 *dest_pixelrow=*tempsrc;
9517 }
9518 }
9519 else
9520 {
9521 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9522 *dest_pixelrow=*tempsrc;
9523 }
9524
9525 dest_pixelrow--;
9526 }
9527 }
9528 }
9529
9530 register_blank_tiles();
9531 redraw=true;
9532 }
9533
9534 break;
9535
9536 case 1: //CTRL
9537 case 0: //None
9538 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9539 redraw=true;
9540
9541 default: //Others
9542 break;
9543 }
9544 }
9545 break;
9546
9547 case KEY_PGUP:
9548 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9549 redraw=true;
9550 break;
9551
9552 case KEY_PGDN:
9553 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9554 redraw=true;
9555 break;
9556
9557 case KEY_HOME:
9558 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9559 redraw=true;
9560 break;
9561
9562 case KEY_END:
9563 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9564 redraw=true;
9565 break;
9566
9567 case KEY_P:
9568 {
9569 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9570
9571 if(whatPage >= 0)
9572 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9573
9574 break;
9575 }
9576
9577 case KEY_O:
9578 if(type==0 && copy>=0)
9579 {
9580 go_tiles();
9581
9582 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9583 {
9584 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9585 saved=false;
9586 }
9587 else
9588 {
9589 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9590 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9591 }
9592
9593 saved=false;
9594 redraw=true;
9595 }
9596
9597 break;
9598
9599 case KEY_E:
9600 if(type==0)
9601 {
9602 edit_tile(tile,flip,cs);
9603 draw_tile_list_window();
9604 redraw=true;
9605 }
9606
9607 break;
9608
9609 case KEY_G:
9610 if(type==0)
9611 {
9612 grab_tile(tile,cs);
9613 draw_tile_list_window();
9614 redraw=true;
9615 }
9616
9617 break;
9618
9619 case KEY_C:
9620 copy=zc_min(tile,tile2);
9621 copycnt=abs(tile-tile2)+1;
9622 redraw=true;
9623 break;
9624
9625 case KEY_X:
9626 if(type==2)
9627 {
9628 ex=(ex+1)%3;
9629 }
9630
9631 break;
9632
9633 case KEY_R:
9634 if(type==2)
9635 break;
9636 if(type==1)
9637 {
9638 flip = rotate_value(flip);
9639 redraw=true;
9640 break;
9641 }
9642
9643 go_tiles();
9644
9645 if(CHECK_CTRL_CMD)
9646 {
9647 bool go=false;
9648 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9649 go=true;
9650 else if(massRecolorSetup(cs))
9651 go=true;
9652
9653 if(go)
9654 {
9655 FOREACH_START(t)
9656 massRecolorApply(t);
9657 FOREACH_END
9658
9659 register_blank_tiles();
9660 }
9661 }
9662 else
9663 {
9664 FOREACH_START(t)
9665 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9666 FOREACH_END
9667 }
9668
9669 redraw=true;
9670 saved=false;
9671 break;
9672
9673 case KEY_SPACE:
9674 rect_sel=!rect_sel;
9675 copy=-1;
9676 redraw=true;
9677 break;
9678
9679 case KEY_H:
9680 flip^=1;
9681 go_tiles();
9682
9683 if(type==0)
9684 {
9685 normalize(tile,tile2,rect_sel,flip);
9686 flip=0;
9687 }
9688
9689 redraw=true;
9690 break;
9691
9692
9693 case KEY_V:
9694 if(copy==-1)
9695 {
9696 if(type!=2)
9697 {
9698 flip^=2;
9699 go_tiles();
9700
9701 if(type==0)
9702 {
9703 normalize(tile,tile2,rect_sel,flip);
9704 flip=0;
9705 }
9706 }
9707 }
9708 else
9709 {
9710 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9711 go_tiles();
9712 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9713 }
9714
9715 redraw=true;
9716 break;
9717
9718 case KEY_F:
9719 if(copy==-1)
9720 {
9721 break;
9722 }
9723 else
9724 {
9725 go_tiles();
9726 {
9727 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9728 }
9729 }
9730
9731 redraw=true;
9732 break;
9733
9734 case KEY_DEL:
9735 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9736 {
9737 bool warn = (rect_sel
9738 && ((tile/20)!=(tile2/20))
9739 && !(tile%20==0&&tile2%20==19));
9740 int32_t z=zc_min(tile,tile2);
9741 int32_t count = abs(tile-tile2) + 1;
9742 tile=z;
9743 tile2=NEWMAXTILES;
9744 copy = tile + count;
9745 copycnt = NEWMAXTILES-copy;
9746 char buf[64];
9747
9748 if(count>1)
9749 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9750 else
9751 sprintf(buf,"Remove tile %d?",tile);
9752
9753 AlertDialog("Remove Tiles", std::string(buf)
9754 +"\nThis will offset the tiles that follow!"
9755 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9756 [&](bool ret,bool)
9757 {
9758 if(ret)
9759 {
9760 go_tiles();
9761 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9762 {
9763 redraw=true;
9764 saved=false;
9765 }
9766 }
9767 }).show();
9768 }
9769 delete_tiles(tile,tile2,rect_sel);
9770 redraw=true;
9771 break;
9772
9773 case KEY_U:
9774 {
9775 if(CHECK_CTRL_CMD)
9776 {
9777 //Only toggle the first 2 bits!
9778 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9779 }
9780 else
9781 {
9782 comeback_tiles();
9783 }
9784
9785 redraw=true;
9786 }
9787 break;
9788
9789 case KEY_8:
9790 case KEY_8_PAD:
9791 hide_8bit_marker();
9792 break;
9793
9794 case KEY_I: //insert tiles
9795 if(type==0)
9796 {
9797 bool warn = (rect_sel
9798 && ((tile/20)!=(tile2/20))
9799 && !(tile%20==0&&tile2%20==19));
9800 int32_t z=zc_min(tile,tile2);
9801 int32_t count = abs(tile-tile2) + 1;
9802 tile=z;
9803 tile2=NEWMAXTILES;
9804 copy = tile + count;
9805 copycnt = NEWMAXTILES-copy;
9806
9807 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9808 {
9809 char buf[64];
9810
9811 if(count>1)
9812 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9813 else
9814 sprintf(buf,"Remove tile %d?",tile);
9815
9816 AlertDialog("Remove Tiles", std::string(buf)
9817 +"\nThis will offset the tiles that follow!"
9818 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9819 [&](bool ret,bool)
9820 {
9821 if(ret)
9822 {
9823 go_tiles();
9824 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9825 {
9826 redraw=true;
9827 saved=false;
9828 }
9829 }
9830 }).show();
9831 }
9832 else
9833 {
9834 char buf[64];
9835
9836 if(count>1)
9837 sprintf(buf,"Insert %d blank tiles?",count);
9838 else
9839 sprintf(buf,"Insert a blank tile?");
9840
9841 AlertDialog("Insert Tiles", std::string(buf)
9842 +"\nThis will offset the tiles that follow!"
9843 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9844 [&](bool ret,bool)
9845 {
9846 if(ret)
9847 {
9848 go_tiles();
9849 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9850 {
9851 redraw=true;
9852 saved=false;
9853 }
9854 }
9855 }).show();
9856 }
9857
9858 copy=-1;
9859 tile2=tile=z;
9860 }
9861 break;
9862 case KEY_M:
9863 if(type==0)
9864 {
9865 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9866 {
9867 go_tiles();
9868 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9869 saved=false;
9870 }
9871 else if(copy==-1)
9872 {
9873 // I don't know what this was supposed to be doing before.
9874 // It didn't work in anything like a sensible way.
9875 if(rect_sel)
9876 {
9877 make_combos_rect(top, left, rows, columns, cs);
9878 }
9879 else
9880 {
9881 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9882 }
9883 }
9884
9885 redraw=true;
9886 }
9887 break;
9888
9889 case KEY_D:
9890 {
9891 int32_t frames=1;
9892 char buf[80];
9893 sprintf(buf, "%d", frames);
9894 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9895 create_relational_tiles_dlg[2].dp=buf;
9896
9897 large_dialog(create_relational_tiles_dlg);
9898
9899 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9900
9901 if(ret==5)
9902 {
9903 frames=zc_max(atoi(buf),1);
9904 bool same = true;
9905 int32_t bitcheck=newtilebuf[tile].format;
9906
9907 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9908 {
9909 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9910 }
9911
9912 if(!same)
9913 {
9914 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9915 break;
9916 }
9917
9918 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9919 {
9920 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9921 break;
9922 }
9923
9924 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9925 {
9926 reset_tile(newtilebuf, tile+i, bitcheck);
9927 }
9928
9929 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9930 {
9931 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9932 {
9933 for(int32_t j=0; j<frames; ++j)
9934 {
9935 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9936 }
9937 }
9938 }
9939 else
9940 {
9941 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9942 {
9943 for(int32_t j=0; j<frames; ++j)
9944 {
9945 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9946 }
9947 }
9948 }
9949 }
9950 register_blank_tiles();
9951 register_used_tiles();
9952 redraw=true;
9953 saved=false;
9954 break;
9955 }
9956
9957 case KEY_B:
9958 {
9959 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9960 bool control=(CHECK_CTRL_CMD);
9961 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9962 int format = control ? tf4Bit : tf8Bit;
9963
9964 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9965 register_blank_tiles();
9966 }
9967 break;
9968 }
9969
9970 clear_keybuf();
9971 }
9972
9973 if(!(key[KEY_Z] || key[KEY_F12]))
9974 did_snap = false;
9975
9976 if(gui_mouse_b()&1)
9977 {
9978 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9979 {
9980 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9981 {
9982 done=1;
9983 }
9984 }
9985
9986 int32_t x=gui_mouse_x()-screen_xofs;
9987 int32_t y=gui_mouse_y()-screen_yofs;
9988
9989 if(y>=0 && y<208*mul)
9990 {
9991 x=zc_min(zc_max(x,0),(320*mul)-1);
9992 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9993
9994 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9995 {
9996 tile2=t;
9997 }
9998 else
9999 {
10000 tile=tile2=t;
10001 }
10002
10003 if(tile_clicked!=t)
10004 {
10005 dclick_status=DCLICK_NOT;
10006 }
10007 else if(dclick_status == DCLICK_AGAIN)
10008 {
10009 while(gui_mouse_b())
10010 {
10011 /* do nothing */
10012 rest(1);
10013 }
10014
10015 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
10016 {
10017 dclick_status=DCLICK_NOT;
10018 }
10019 else
10020 {
10021 if(type==0)
10022 {
10023 edit_tile(tile,flip,cs);
10024 draw_tile_list_window();
10025 redraw=true;
10026 }
10027 else
10028 {
10029 done=2;
10030 }
10031 }
10032 }
10033
10034 tile_clicked=t;
10035 }
10036 else if(x>300*mul && !bdown)
10037 {
10038 if(y<224*mul && first>0)
10039 {
10040 first-=TILES_PER_PAGE;
10041 redraw=true;
10042 }
10043
10044 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
10045 {
10046 first+=TILES_PER_PAGE;
10047 redraw=true;
10048 }
10049
10050 bdown=true;
10051 }
10052
10053 if(type==1||type==2)
10054 {
10055 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
10056 done=1;
10057
10058 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
10059 done=2;
10060 }
10061 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
10062 {
10063 rect_sel=!rect_sel;
10064 copy=-1;
10065 redraw=true;
10066 }
10067 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
10068 {
10069 FONT *tf = font;
10070 font = tfont;
10071
10072 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
10073 {
10074 font = tf;
10075 grab_tile(tile,cs);
10076 draw_tile_list_window();
10077 position_mouse_z(0);
10078 redraw=true;
10079 }
10080
10081 font = tf;
10082 }
10083 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10084 {
10085 FONT *tf = font;
10086 font = tfont;
10087
10088 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10089 {
10090 font = tf;
10091 edit_tile(tile,flip,cs);
10092 draw_tile_list_window();
10093 redraw=true;
10094 }
10095
10096 font = tf;
10097 }
10098 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10099 {
10100 FONT *tf = font;
10101 font = tfont;
10102
10103 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10104 {
10105 std::string initial_path = "tileset.png";
10106 if (strlen(datapath))
10107 initial_path = fmt::format("{}/{}", datapath, initial_path);
10108 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10109 {
10110 PALETTE temppal;
10111 get_palette(temppal);
10112 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10113 draw_tiles(tempbmp,first,cs,f,false,true);
10114 save_bitmap(temppath, tempbmp, RAMpal);
10115 destroy_bitmap(tempbmp);
10116 }
10117 }
10118
10119 font = tf;
10120 }
10121 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10122 {
10123 FONT *tf = font;
10124 font = tfont;
10125
10126 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10127 {
10128 if(massRecolorSetup(cs))
10129 {
10130 go_tiles();
10131
10132 FOREACH_START(t)
10133 massRecolorApply(t);
10134 FOREACH_END
10135
10136 register_blank_tiles();
10137 }
10138 }
10139
10140 font = tf;
10141 }
10142 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10143 {
10144 FONT *tf = font;
10145 font = tfont;
10146
10147 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10148 {
10149 done=1;
10150 }
10151
10152 font = tf;
10153 }
10154
10155 bdown=true;
10156 }
10157
10158 bool r_click = false;
10159
10160 if(gui_mouse_b()&2 && !bdown && type==0)
10161 {
10162 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10163 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10164
10165 if(y>=0 && y<208*mul)
10166 {
10167 x=zc_min(zc_max(x,0),(320*mul)-1);
10168 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10169
10170 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10171 tile=tile2=t;
10172 }
10173
10174 bdown = r_click = true;
10175 f=8;
10176 }
10177
10178 if(gui_mouse_b()==0)
10179 bdown=false;
10180
10181 position_mouse_z(0);
10182
10183 REDRAW:
10184
10185 if((f%8)==0 || InvalidBG == 1)
10186 redraw=true;
10187 if(otl != tile || otl2 != tile2)
10188 {
10189 otl = tile;
10190 otl2 = tile2;
10191 redraw = true;
10192 }
10193
10194 if(redraw)
10195 {
10196 draw_tiles(first,cs,f);
10197 }
10198 if(f&8)
10199 {
10200 if(rect_sel)
10201 {
10202 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10203 zc_min(TILECOL(tile),TILECOL(tile2));
10204 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10205 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10206 {
10207 if(i>=first && i<first+TILES_PER_PAGE &&
10208 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10209 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10210 {
10211 int32_t x=TILECOL(i)<<(5);
10212 int32_t y=TILEROW(i-first)<<(5);
10213 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10214 }
10215 }
10216 }
10217 else
10218 {
10219 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10220 {
10221 if(i>=first && i<first+TILES_PER_PAGE)
10222 {
10223 int32_t x=TILECOL(i)<<(5);
10224 int32_t y=TILEROW(i-first)<<(5);
10225 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10226 }
10227 }
10228 }
10229 }
10230
10231 if(type==0)
10232 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10233 else
10234 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10235
10236 if(type==2)
10237 {
10238 char cbuf[16];
10239 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10240 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10241 }
10242
10243 ++f;
10244
10245 if(r_click)
10246 {
10247 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10248 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10249 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10250 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10251
10252 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10253 if (newtilebuf[tile].format == tf8Bit)
10254 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10255 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10256 select_tile_color_depth_cb = [&](int format){
10257 if (newtilebuf[tile].format == format)
10258 return;
10259
10260 bool skip_prompt = true;
10261 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10262 };
10263
10264 NewMenu rcmenu
10265 {
10266 { "Copy", [&]()
10267 {
10268 copy = zc_min(tile,tile2);
10269 copycnt = abs(tile-tile2)+1;
10270 } },
10271 { "Paste", [&]()
10272 {
10273 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10274 if(saved) saved = !b;
10275 }, nullopt, copy < 0 },
10276 { "Move", [&]()
10277 {
10278 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10279 if(saved) saved = !b;
10280 }, nullopt, copy < 0 },
10281 { "Clear", [&]()
10282 {
10283 delete_tiles(tile, tile2, rect_sel);
10284 } },
10285 { "Set as Reference", [&]()
10286 {
10287 reftile = tile;
10288 } },
10289 {},
10290 { "Edit", [&]()
10291 {
10292 edit_tile(tile, flip, cs);
10293 draw_tile_list_window();
10294 } },
10295 { "Grab", [&]()
10296 {
10297 grab_tile(tile, cs);
10298 draw_tile_list_window();
10299 position_mouse_z(0);
10300 } },
10301 { "Scale", [&]()
10302 {
10303 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10304 if(saved) saved = !b;
10305 }, nullopt, type != 0 },
10306 { "Angular Rotation", [&]()
10307 {
10308 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10309 if(saved) saved = !b;
10310 }, nullopt, type != 0 },
10311 { "Color Depth", &select_tile_color_depth_menu },
10312 {},
10313 { "Blank?", [&]()
10314 {
10315 show_blank_tile(tile);
10316 } },
10317 {},
10318 { "View ", &select_tile_view_menu },
10319 { "Overlay", [&]()
10320 {
10321 overlay_tile(newtilebuf, tile, copy, cs, 0);
10322 } },
10323 { "H-Flip", [&]()
10324 {
10325 flip ^= 1;
10326 go_tiles();
10327
10328 if(type == 0)
10329 {
10330 normalize(tile, tile2, rect_sel, flip);
10331 flip = 0;
10332 }
10333 } },
10334 { "V-Flip", [&]()
10335 {
10336 flip ^= 2;
10337 go_tiles();
10338
10339 if(type == 0)
10340 {
10341 normalize(tile, tile2, rect_sel, flip);
10342 flip = 0;
10343 }
10344 } },
10345 { "Create Combos", [&]()
10346 {
10347 if(rect_sel)
10348 make_combos_rect(top, left, rows, columns, cs);
10349 else
10350 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10351 }, nullopt, type != 0 },
10352 { "Insert", [&]()
10353 {
10354 bool warn = (rect_sel
10355 && ((tile/20)!=(tile2/20))
10356 && !(tile%20==0&&tile2%20==19));
10357 int32_t z = zc_min(tile, tile2);
10358 int32_t count = abs(tile-tile2) + 1;
10359 tile = z;
10360 tile2 = NEWMAXTILES;
10361 copy = tile + count;
10362 copycnt = NEWMAXTILES-copy;
10363
10364 string msg;
10365
10366 if(count>1)
10367 msg = fmt::format("Insert {} blank tiles?",count);
10368 else
10369 msg = "Insert a blank tile?";
10370
10371 AlertDialog("Insert Tiles", msg
10372 +"\nThis will offset the tiles that follow!"
10373 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10374 [&](bool ret,bool)
10375 {
10376 if(ret)
10377 {
10378 go_tiles();
10379 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10380 saved = false;
10381 }
10382 }).show();
10383
10384 copy=-1;
10385 tile2=tile=z;
10386 }, nullopt, type != 0 },
10387 { "Remove", [&]()
10388 {
10389 bool warn = (rect_sel
10390 && ((tile/20)!=(tile2/20))
10391 && !(tile%20==0&&tile2%20==19));
10392 int32_t z = zc_min(tile, tile2);
10393 int32_t count = abs(tile-tile2) + 1;
10394 tile = z;
10395 tile2 = NEWMAXTILES;
10396 copy = tile + count;
10397 copycnt = NEWMAXTILES-copy;
10398
10399 string msg;
10400
10401 if(count>1)
10402 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10403 else
10404 msg = fmt::format("Remove tile {}?", tile);
10405
10406 AlertDialog("Remove Tiles", msg
10407 +"\nThis will offset the tiles that follow!"
10408 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10409 [&](bool ret,bool)
10410 {
10411 if(ret)
10412 {
10413 go_tiles();
10414 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10415 saved = false;
10416 }
10417 }).show();
10418
10419 copy=-1;
10420 tile2=tile=z;
10421 }, nullopt, type != 0 },
10422 };
10423 rcmenu.pop(window_mouse_x(),window_mouse_y());
10424 redraw = true;
10425 r_click = false;
10426 goto REDRAW;
10427 }
10428 update_hw_screen();
10429 }
10430 while(!done);
10431
10432 while(gui_mouse_b())
10433 {
10434 /* do nothing */
10435 rest(1);
10436 }
10437
10438 comeback();
10439 register_blank_tiles();
10440 register_used_tiles();
10441 setup_combo_animations();
10442 setup_combo_animations2();
10443 int32_t ret = done-1;
10444 if(ret)
10445 {
10446 _selected_tile = tile;
10447 _selected_tcset = cs;
10448 }
10449
10450 popup_zqdialog_end();
10451 return ret;
10452 }
10453 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10454 {
10455 if(_selected_tile > -1)
10456 {
10457 tile = _selected_tile;
10458 cs = _selected_tcset;
10459 }
10460 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10461 if(_selected_tile < 0)
10462 {
10463 _selected_tile = tile;
10464 _selected_tcset = cs;
10465 }
10466 return ret;
10467 }
10468
10469 int32_t onTiles()
10470 {
10471 return onGotoTiles(-1);
10472 }
10473
10474 int32_t onGotoTiles(int32_t startfrom)
10475 {
10476 static int32_t t = 0;
10477 if (startfrom > -1)
10478 t = startfrom;
10479 int32_t f = 0;
10480 int32_t c = CSet;
10481 reset_pal_cycling();
10482 // loadlvlpal(Map.CurrScr()->color);
10483 rebuild_trans_table();
10484 select_tile(t, f, 0, c, true);
10485 refresh(rALL);
10486 return D_O_K;
10487 }
10488
10489 int32_t combopage_animate = 1;
10490 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10491 {
10492 if(unsigned(c)<MAXCOMBOS)
10493 {
10494 newcombo& cmb = combobuf[c];
10495 int t = cmb.tile;
10496 if(!animate)
10497 cmb.tile = cmb.o_tile;
10498 put_combo(dest,x,y,c,cs,0,0);
10499 cmb.tile = t;
10500 }
10501 else
10502 {
10503 rectfill(dest,x,y,x+32-1,y+32-1,0);
10504 }
10505 }
10506
10507 void draw_combos(int32_t page,int32_t cs,bool cols)
10508 {
10509 clear_bitmap(screen2);
10510 BITMAP *buf = create_bitmap_ex(8,16,16);
10511
10512 int32_t w = 32;
10513 int32_t h = 32;
10514 int32_t mul = 2;
10515
10516 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10517 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10518 int32_t screen_xofs=window_xofs+6;
10519 int32_t screen_yofs=window_yofs+25;
10520
10521 if(cols==false)
10522 {
10523 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10524 {
10525 int32_t x = (i%COMBOS_PER_ROW)*w;
10526 int32_t y = (i/COMBOS_PER_ROW)*h;
10527
10528 combotile_override_x = x+screen_xofs+(w-16)/2;
10529 combotile_override_y = y+screen_yofs+(h-16)/2;
10530 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10531 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10532 }
10533 }
10534 else
10535 {
10536 int32_t c = 0;
10537
10538 for(int32_t i=0; i<256; i++)
10539 {
10540 int32_t x = (i%COMBOS_PER_ROW)*w;
10541 int32_t y = (i/COMBOS_PER_ROW)*h;
10542
10543 combotile_override_x = x+screen_xofs+(w-16)/2;
10544 combotile_override_y = y+screen_yofs+(h-16)/2;
10545 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10546 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10547 ++c;
10548
10549 if((i&3)==3)
10550 c+=48;
10551
10552 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10553 c-=256;
10554 }
10555 }
10556 combotile_override_x = combotile_override_y = -1;
10557
10558 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10559 {
10560 vline(screen2,x,0,(208*mul)-1,vc(15));
10561 }
10562
10563 destroy_bitmap(buf);
10564 }
10565
10566 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10567 {
10568 int32_t yofs=3;
10569 static BITMAP *buf = create_bitmap_ex(8,16,16);
10570 int32_t mul = 2;
10571 FONT *tfont = get_zc_font(font_lfont_l);
10572
10573 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10574 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10575 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10576
10577 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10578
10579 if(copy>=0)
10580 {
10581 put_combo(buf,0,0,copy,cs,0,0);
10582 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10583
10584 if(copycnt>1)
10585 {
10586 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10587 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10588 }
10589 else
10590 {
10591 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10592 }
10593 }
10594 else
10595 {
10596 if (InvalidBG == 2)
10597 {
10598 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10599 }
10600 else if(InvalidBG == 1)
10601 {
10602 for(int32_t dy=0; dy<16*mul; dy++)
10603 {
10604 for(int32_t dx=0; dx<16*mul; dx++)
10605 {
10606 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10607 }
10608 }
10609 }
10610 else
10611 {
10612 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10613 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10614 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10615 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10616 }
10617 }
10618
10619 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10620 put_combo(buf,0,0,tile,cs,0,0);
10621 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10622
10623 if(tile>tile2)
10624 {
10625 zc_swap(tile,tile2);
10626 }
10627
10628 char cbuf[8];
10629 cbuf[0]=0;
10630
10631 if(tile2!=tile)
10632 {
10633 sprintf(cbuf,"-%d",tile2);
10634 }
10635
10636 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10637 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10638
10639 if(tile2==tile)
10640 {
10641 int32_t nextcombo=combobuf[tile].nextcombo;
10642 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10643 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10644
10645 if(nextcombo>0 && !(combobuf[tile].animflags & AF_CYCLEUNDERCOMBO))
10646 {
10647 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10648 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10649 }
10650 else
10651 {
10652 if (InvalidBG == 2)
10653 {
10654 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10655 }
10656 else if(InvalidBG == 1)
10657 {
10658 for(int32_t dy=0; dy<16*mul; dy++)
10659 {
10660 for(int32_t dx=0; dx<16*mul; dx++)
10661 {
10662 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10663 }
10664 }
10665 }
10666 else
10667 {
10668 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10669 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10670 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10671 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10672 }
10673 }
10674
10675 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10676 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10677 }
10678
10679
10680 FONT *tf = font;
10681 font = tfont;
10682
10683 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10684 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10685
10686 if(buttons&2)
10687 {
10688 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10689 }
10690
10691 if(buttons&4)
10692 {
10693 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10694 }
10695
10696 font = tf;
10697
10698 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10699 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10700 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10701 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10702
10703 int32_t w = 640;
10704 int32_t h = 480;
10705 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10706 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10707 int32_t screen_xofs=window_xofs+6;
10708 int32_t screen_yofs=window_yofs+25;
10709
10710 custom_vsync();
10711 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10712 SCRFIX();
10713 //destroy_bitmap(buf);
10714 }
10715
10716 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10717 {
10718 int32_t page = tile&0xFF00;
10719 tile &= 0xFF;
10720
10721 if(!cols)
10722 tile += s;
10723 else
10724 {
10725 if(s==-COMBOS_PER_ROW)
10726 tile-=4;
10727
10728 if(s==COMBOS_PER_ROW)
10729 tile+=4;
10730
10731 if(s==-1)
10732 tile-=1;
10733
10734 if(s==1)
10735 tile+=1;
10736 }
10737
10738 /*
10739 if(s==1)
10740 {
10741 if((tile&3)==3)
10742 tile+=48;
10743 else
10744 ++tile;
10745 }
10746 if(s==-1)
10747 {
10748 if((tile&3)==0)
10749 tile-=48;
10750 else
10751 --tile;
10752 }
10753 }
10754 */
10755 bound(tile,0,255);
10756 tile += page;
10757
10758 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10759 tile2 = tile;
10760 }
10761
10762 void draw_combo_list_window()
10763 {
10764 int32_t window_xofs=0;
10765 int32_t window_yofs=0;
10766 int32_t w = 640;
10767 int32_t h = 480;
10768
10769 window_xofs=(zq_screen_w-w-12)>>1;
10770 window_yofs=(zq_screen_h-h-25-6)>>1;
10771 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10772 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10773 FONT *oldfont = font;
10774 font = get_zc_font(font_lfont);
10775 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10776 font=oldfont;
10777 }
10778
10779
10780 static int32_t _selected_combo=-1, _selected_cset=-1;
10781 bool select_combo_2(int32_t &cmb,int32_t &cs)
10782 {
10783 popup_zqdialog_start();
10784 reset_combo_animations();
10785 reset_combo_animations2();
10786 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10787 // static int32_t cmb=0;
10788 int32_t page=cmb>>8;
10789 int32_t tile2=cmb;
10790 int32_t done=0;
10791 int32_t tile_clicked=-1;
10792 int32_t t2;
10793 int32_t copy=-1;
10794 int32_t copycnt=0;
10795
10796 position_mouse_z(0);
10797
10798 go();
10799 int32_t w = 640;
10800 int32_t h = 480;
10801 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10802 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10803 int32_t screen_xofs=window_xofs+6;
10804 int32_t screen_yofs=window_yofs+25;
10805 int32_t panel_yofs=3;
10806 int32_t mul = 2;
10807 FONT *tfont = get_zc_font(font_lfont_l);
10808
10809 draw_combo_list_window();
10810 draw_combos(page,cs,true);
10811 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10812
10813 while(gui_mouse_b())
10814 {
10815 /* do nothing */
10816 rest(1);
10817 }
10818
10819 bool bdown=false;
10820 int32_t f=0;
10821 int otl = cmb, otl2 = tile2;
10822
10823 do
10824 {
10825 HANDLE_CLOSE_ZQDLG();
10826 if(exiting_program) break;
10827 rest(4);
10828 bool redraw=false;
10829
10830 if(mouse_z<0)
10831 {
10832 if(page<COMBO_PAGES-1)
10833 {
10834 ++page;
10835 cmb=tile2=(page<<8)+(cmb&0xFF);
10836 }
10837
10838 position_mouse_z(0);
10839 redraw=true;
10840 }
10841 else if(mouse_z>0)
10842 {
10843 if(page>0)
10844 {
10845 --page;
10846 cmb=tile2=(page<<8)+(cmb&0xFF);
10847 }
10848
10849 position_mouse_z(0);
10850 redraw=true;
10851 }
10852
10853 if(keypressed())
10854 {
10855 switch(readkey()>>8)
10856 {
10857 case KEY_DEL:
10858 cmb=0;
10859 done=2;
10860 break;
10861
10862 case KEY_ENTER_PAD:
10863 case KEY_ENTER:
10864 done=2;
10865 break;
10866
10867 case KEY_ESC:
10868 done=1;
10869 break;
10870
10871 case KEY_F1:
10872 onHelp();
10873 break;
10874
10875 case KEY_EQUALS:
10876 case KEY_PLUS_PAD:
10877 cs = (cs<13) ? cs+1:0;
10878 redraw=true;
10879 break;
10880
10881 case KEY_MINUS:
10882 case KEY_MINUS_PAD:
10883 cs = (cs>0) ? cs-1:13;
10884 redraw=true;
10885 break;
10886
10887 case KEY_UP:
10888 sel_combo(cmb,tile2,-COMBOS_PER_ROW,true);
10889 redraw=true;
10890 break;
10891
10892 case KEY_DOWN:
10893 sel_combo(cmb,tile2,COMBOS_PER_ROW,true);
10894 redraw=true;
10895 break;
10896
10897 case KEY_LEFT:
10898 sel_combo(cmb,tile2,-1,true);
10899 redraw=true;
10900 break;
10901
10902 case KEY_RIGHT:
10903 sel_combo(cmb,tile2,1,true);
10904 redraw=true;
10905 break;
10906
10907 case KEY_PGUP:
10908 if(page>0)
10909 {
10910 --page;
10911 cmb=tile2=(page<<8)+(cmb&0xFF);
10912 }
10913
10914 redraw=true;
10915 break;
10916
10917 case KEY_PGDN:
10918 if(page<COMBO_PAGES-1)
10919 {
10920 ++page;
10921 cmb=tile2=(page<<8)+(cmb&0xFF);
10922 }
10923
10924 redraw=true;
10925 break;
10926
10927 case KEY_P:
10928 {
10929 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10930
10931 if(!cancelgetnum)
10932 page=(zc_min(choosepage,COMBO_PAGES-1));
10933
10934 cmb=tile2=(page<<8)+(cmb&0xFF);
10935 redraw=true;
10936 break;
10937 }
10938 }
10939
10940 clear_keybuf();
10941 }
10942
10943 if(gui_mouse_b()&1)
10944 {
10945 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10946 {
10947 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10948 {
10949 done=1;
10950 }
10951 }
10952
10953 int32_t x=gui_mouse_x()-screen_xofs;
10954 int32_t y=gui_mouse_y()-screen_yofs;
10955
10956 if(y>=0 && y<208*mul)
10957 {
10958 x=zc_min(zc_max(x,0),(320*mul)-1);
10959 int32_t t;
10960
10961 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10962
10963 bound(t,0,255);
10964 t+=page<<8;
10965 cmb=tile2=t;
10966
10967 if(tile_clicked!=t)
10968 {
10969 dclick_status=DCLICK_NOT;
10970 }
10971 else if(dclick_status == DCLICK_AGAIN)
10972 {
10973 while(gui_mouse_b())
10974 {
10975 /* do nothing */
10976 }
10977
10978 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10979
10980 if(t2!=t)
10981 {
10982 dclick_status=DCLICK_NOT;
10983 }
10984 else
10985 {
10986 done=2;
10987 }
10988 }
10989
10990 tile_clicked=t;
10991 }
10992 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10993 {
10994 if(y<(224*mul)+panel_yofs && page>0)
10995 {
10996 --page;
10997 redraw=true;
10998 }
10999
11000 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11001 {
11002 ++page;
11003 redraw=true;
11004 }
11005
11006 bdown=true;
11007 }
11008
11009 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
11010 {
11011 FONT *tf = font;
11012 font = tfont;
11013
11014 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11015 {
11016 done=2;
11017 }
11018
11019 font = tf;
11020 }
11021 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11022 {
11023 FONT *tf = font;
11024 font = tfont;
11025
11026 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11027 combopage_animate = combopage_animate ? 0 : 1;
11028 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11029 redraw = true;
11030
11031 font = tf;
11032 }
11033
11034 bdown=true;
11035 }
11036
11037 bool r_click = false;
11038
11039 if(gui_mouse_b()&2 && !bdown)
11040 {
11041 int32_t x=gui_mouse_x()+screen_xofs;
11042 int32_t y=gui_mouse_y()+screen_yofs;
11043
11044 if(y>=0 && y<208*mul)
11045 {
11046 x=zc_min(zc_max(x,0),(320*mul)-1);
11047 int32_t t;
11048
11049 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11050
11051 bound(t,0,255);
11052 t+=page<<8;
11053
11054 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
11055 cmb=tile2=t;
11056 }
11057
11058 bdown = r_click = true;
11059 f=8;
11060 }
11061
11062 if(gui_mouse_b()==0)
11063 bdown=false;
11064
11065 if((f%8) || InvalidBG == 1)
11066 redraw = true;
11067 if(otl != cmb || otl2 != tile2)
11068 {
11069 otl = cmb;
11070 otl2 = tile2;
11071 redraw = true;
11072 }
11073
11074 if(redraw || combopage_animate)
11075 draw_combos(page,cs,true);
11076
11077 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11078
11079 if(f&8)
11080 {
11081 int32_t x,y;
11082
11083 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11084 {
11085 if((i>>8)==page)
11086 {
11087 int32_t t=i&255;
11088
11089 x=((t&3) + ((t/52)<<2)) << 5;
11090 y=((t%52)>>2) << 5;
11091
11092 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11093 }
11094 }
11095
11096 SCRFIX();
11097 }
11098
11099 ++f;
11100
11101 }
11102 while(!done);
11103
11104 while(gui_mouse_b())
11105 {
11106 /* do nothing */
11107 rest(1);
11108 }
11109
11110 comeback();
11111 setup_combo_animations();
11112 setup_combo_animations2();
11113
11114 bool ret = done==2;
11115 if(ret)
11116 {
11117 _selected_combo = cmb;
11118 _selected_cset = cs;
11119 }
11120
11121 popup_zqdialog_end();
11122 return ret;
11123 }
11124
11125 bool select_combo_3(int32_t &cmb,int32_t &cs)
11126 {
11127 if(_selected_combo < 0)
11128 {
11129 _selected_combo = Combo;
11130 _selected_cset = CSet;
11131 }
11132 cmb = _selected_combo;
11133 cs = _selected_cset;
11134 return select_combo_2(cmb,cs);
11135 }
11136
11137 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11138 {
11139 static bitstring pasteflags;
11140 static const vector<CheckListInfo> advp_names =
11141 {
11142 { "Tile" },
11143 { "CSet2" },
11144 { "Solidity" },
11145 { "Animation" },
11146 { "Type" },
11147 { "Inherent Flag" },
11148 { "Attribytes" },
11149 { "Attrishorts" },
11150 { "Attributes" },
11151 { "Flags", "The 16 Flags on the 'Flags' tab" },
11152 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11153 { "Label" },
11154 { "Script" },
11155 { "Effect" },
11156 { "Triggers Tab" },
11157 { "Lifting Tab" },
11158 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11159 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11160 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11161 };
11162 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11163 return false;
11164
11165 //Paste to each combo in the range
11166 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11167 {
11168 combobuf[i].advpaste(combobuf[copy], pasteflags);
11169 }
11170
11171 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11172 {
11173 setup_combo_animations();
11174 setup_combo_animations2();
11175 }
11176
11177 return true;
11178 }
11179
11180 int32_t combo_screen(int32_t pg, int32_t tl)
11181 {
11182 popup_zqdialog_start();
11183 reset_combo_animations();
11184 reset_combo_animations2();
11185 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11186 static int32_t tile=0;
11187 static int32_t page=0;
11188
11189 if(pg>-1)
11190 page = pg;
11191
11192 if(tl>-1)
11193 tile = tl;
11194
11195 int32_t tile2=tile;
11196 int32_t done=0;
11197 int32_t cs = CSet;
11198 int32_t copy=-1;
11199 int32_t copycnt=0;
11200
11201 int32_t tile_clicked=-1;
11202 int32_t t2;
11203
11204 bool masscopy;
11205
11206 go();
11207 int32_t w = 640;
11208 int32_t h = 480;
11209 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11210 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11211 int32_t screen_xofs=window_xofs+6;
11212 int32_t screen_yofs=window_yofs+25;
11213 int32_t panel_yofs=3;
11214 int32_t mul = 2;
11215 FONT *tfont = get_zc_font(font_lfont_l);
11216
11217 draw_combo_list_window();
11218 draw_combos(page,cs,true);
11219 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11220 go_combos();
11221 position_mouse_z(0);
11222
11223 while(gui_mouse_b())
11224 {
11225 /* do nothing */
11226 }
11227
11228 bool bdown=false;
11229 int32_t f=0;
11230 int otl = tile, otl2 = tile2;
11231
11232 do
11233 {
11234 HANDLE_CLOSE_ZQDLG();
11235 if(exiting_program) break;
11236 rest(4);
11237 bool redraw=false;
11238
11239 if(mouse_z<0)
11240 {
11241 if(page<COMBO_PAGES-1)
11242 {
11243 ++page;
11244 tile=tile2=(page<<8)+(tile&0xFF);
11245 }
11246
11247 position_mouse_z(0);
11248 redraw=true;
11249 }
11250 else if(mouse_z>0)
11251 {
11252 if(page>0)
11253 {
11254 --page;
11255 tile=tile2=(page<<8)+(tile&0xFF);
11256 }
11257
11258 position_mouse_z(0);
11259 redraw=true;
11260 }
11261
11262 if(keypressed())
11263 {
11264 switch(readkey()>>8)
11265 {
11266 case KEY_ENTER_PAD:
11267 case KEY_ENTER:
11268 done=2;
11269 break;
11270
11271 case KEY_ESC:
11272 done=1;
11273 break;
11274
11275 case KEY_F1:
11276 onHelp();
11277 break;
11278
11279 case KEY_EQUALS:
11280 case KEY_PLUS_PAD:
11281 if(CHECK_CTRL_CMD)
11282 {
11283 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11284 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11285 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11286
11287 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11288 {
11289 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11290 0, NEWMAXTILES-1));
11291 }
11292
11293 setup_combo_animations();
11294 redraw=true;
11295 }
11296 else
11297 {
11298 cs = (cs<13) ? cs+1:0;
11299 redraw=true;
11300 }
11301
11302 break;
11303
11304 case KEY_MINUS:
11305 case KEY_MINUS_PAD:
11306 if(CHECK_CTRL_CMD)
11307 {
11308 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11309 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11310 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11311
11312 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11313 {
11314 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11315 0, NEWMAXTILES-1));
11316 }
11317
11318 setup_combo_animations();
11319 redraw=true;
11320 }
11321 else
11322 {
11323 cs = (cs>0) ? cs-1:13;
11324 redraw=true;
11325 }
11326
11327 break;
11328
11329 case KEY_UP:
11330 sel_combo(tile,tile2,-COMBOS_PER_ROW,true);
11331 redraw=true;
11332 break;
11333
11334 case KEY_DOWN:
11335 sel_combo(tile,tile2,COMBOS_PER_ROW,true);
11336 redraw=true;
11337 break;
11338
11339 case KEY_LEFT:
11340 sel_combo(tile,tile2,-1,true);
11341 redraw=true;
11342 break;
11343
11344 case KEY_RIGHT:
11345 sel_combo(tile,tile2,1,true);
11346 redraw=true;
11347 break;
11348
11349 case KEY_PGUP:
11350 if(page>0)
11351 {
11352 --page;
11353 tile=tile2=(page<<8)+(tile&0xFF);
11354 }
11355
11356 redraw=true;
11357 break;
11358
11359 case KEY_PGDN:
11360 if(page<COMBO_PAGES-1)
11361 {
11362 ++page;
11363 tile=tile2=(page<<8)+(tile&0xFF);
11364 }
11365
11366 redraw=true;
11367 break;
11368
11369 case KEY_A:
11370 {
11371 tile=(page<<8);
11372 tile2=(page<<8)+(0xFF);
11373 }
11374
11375 redraw=true;
11376 break;
11377
11378 case KEY_P:
11379 {
11380 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11381
11382 if(!cancelgetnum)
11383 page=(zc_min(choosepage,COMBO_PAGES-1));
11384
11385 tile=tile2=(page<<8)+(tile&0xFF);
11386 redraw=true;
11387 }
11388 break;
11389
11390 case KEY_U:
11391 comeback_combos();
11392 redraw=true;
11393 break;
11394
11395 case KEY_E:
11396 go_combos();
11397 edit_combo(tile,false,cs);
11398 redraw=true;
11399 setup_combo_animations();
11400 setup_combo_animations2();
11401 break;
11402
11403 case KEY_C:
11404 go_combos();
11405 copy=zc_min(tile,tile2);
11406 copycnt=abs(tile-tile2)+1;
11407 redraw=true;
11408 break;
11409
11410 case KEY_H:
11411 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11412 {
11413 combobuf[i].flip^=1;
11414 byte w2=combobuf[i].walk;
11415 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11416 w2=combobuf[i].csets;
11417 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11418 }
11419
11420 redraw=true;
11421 saved=false;
11422 break;
11423
11424 case KEY_M:
11425 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11426 {
11427 move_combos(tile,tile2,copy,copycnt);
11428 saved=false;
11429 }
11430
11431 redraw=true;
11432 break;
11433
11434 case KEY_S:
11435 tile=tile2=zc_min(tile,tile2);
11436
11437 if(copy>=0 && tile!=copy)
11438 {
11439 go_combos();
11440
11441 for(int32_t i=0; i<copycnt; i++)
11442 {
11443 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11444 }
11445
11446 saved=false;
11447 setup_combo_animations();
11448 setup_combo_animations2();
11449 }
11450
11451 redraw=true;
11452 copy=-1;
11453 break;
11454
11455 case KEY_V:
11456 if((CHECK_CTRL_CMD) && copy != -1)
11457 {
11458 if(advpaste(tile, tile2, copy))
11459 {
11460 saved=false;
11461 redraw=true;
11462 copy=-1;
11463 }
11464
11465 break;
11466 }
11467
11468 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11469
11470 if(copy==-1)
11471 {
11472 go_combos();
11473
11474 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11475 {
11476 combobuf[i].flip^=2;
11477 byte w2=combobuf[i].walk;
11478 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11479 w2=combobuf[i].csets;
11480 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11481 }
11482
11483 saved=false;
11484 }
11485 else
11486 {
11487 go_combos();
11488 copy_combos(tile,tile2,copy,copycnt,masscopy);
11489 setup_combo_animations();
11490 setup_combo_animations2();
11491 saved=false;
11492 }
11493
11494 redraw=true;
11495 break;
11496 case KEY_R:
11497 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11498 {
11499 combobuf[i].flip = rotate_value(combobuf[i].flip);
11500 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11501 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11502 }
11503
11504 redraw=true;
11505 saved=false;
11506 break;
11507
11508 case KEY_I:
11509 {
11510 // rev.1509; Can now insert/remove all selected combos
11511 int32_t z=tile;
11512 int32_t numSelected = abs(tile-tile2) + 1;
11513 tile=zc_min(tile,tile2);
11514 tile2=MAXCOMBOS;
11515 copy = tile + numSelected; // copy=tile+1;
11516 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11517
11518 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11519 {
11520 char buf[64];
11521
11522 if(numSelected>1)
11523 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11524 else
11525 sprintf(buf,"Remove combo %d?",tile);
11526
11527 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11528 {
11529 move_combos(tile,tile2,copy, copycnt);
11530 //don't allow the user to undo; quest combo references are incorrect -DD
11531 go_combos();
11532 redraw=true;
11533 saved=false;
11534 }
11535 }
11536 else
11537 {
11538 char buf[64];
11539
11540 if(numSelected>1)
11541 sprintf(buf,"Insert %d blank combos?",numSelected);
11542 else
11543 sprintf(buf,"Insert a blank combo?");
11544
11545 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11546 {
11547 move_combos(copy,tile2,tile, copycnt);
11548 go_combos();
11549 redraw=true;
11550 saved=false;
11551 }
11552 }
11553
11554 copy=-1;
11555 tile2=tile=z;
11556 }
11557 break;
11558
11559 case KEY_DEL:
11560 {
11561 char buf[40];
11562
11563 if(tile==tile2)
11564 {
11565 sprintf(buf,"Delete combo %d?",tile);
11566 }
11567 else
11568 {
11569 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11570 }
11571
11572 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11573 {
11574 go_combos();
11575
11576 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11577 {
11578 clear_combo(i);
11579 }
11580
11581 tile=tile2=zc_min(tile,tile2);
11582 redraw=true;
11583 saved=false;
11584 setup_combo_animations();
11585 setup_combo_animations2();
11586 }
11587 }
11588 break;
11589 }
11590
11591 clear_keybuf();
11592 }
11593
11594 if(gui_mouse_b()&1)
11595 {
11596 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11597 {
11598 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11599 {
11600 done=1;
11601 }
11602 }
11603
11604 int32_t x=gui_mouse_x()-screen_xofs;
11605 int32_t y=gui_mouse_y()-screen_yofs;
11606
11607 if(y>=0 && y<(208*mul))
11608 {
11609 x=zc_min(zc_max(x,0),(320*mul)-1);
11610 int32_t t;
11611
11612 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11613
11614 bound(t,0,255);
11615 t+=page<<8;
11616
11617 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11618 {
11619 tile2=t;
11620 }
11621 else
11622 {
11623 tile=tile2=t;
11624 }
11625
11626 if(tile_clicked!=t)
11627 {
11628 dclick_status=DCLICK_NOT;
11629 }
11630 else if(dclick_status == DCLICK_AGAIN)
11631 {
11632 while(gui_mouse_b())
11633 {
11634 /* do nothing */
11635 rest(1);
11636 }
11637
11638 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11639
11640 bound(t2,0,255);
11641 t2+=page<<8;
11642
11643 if(t2!=t)
11644 {
11645 dclick_status=DCLICK_NOT;
11646 }
11647 else
11648 {
11649 go_combos();
11650 edit_combo(tile,false,cs);
11651 redraw=true;
11652 setup_combo_animations();
11653 setup_combo_animations2();
11654 }
11655 }
11656
11657 tile_clicked=t;
11658 }
11659 else if(x>(300*mul) && !bdown)
11660 {
11661 if(y<(224*mul)+panel_yofs && page>0)
11662 {
11663 --page;
11664 redraw=true;
11665 }
11666
11667 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11668 {
11669 ++page;
11670 redraw=true;
11671 }
11672
11673 bdown=true;
11674 }
11675
11676 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11677 {
11678 FONT *tf = font;
11679 font = tfont;
11680
11681 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11682 {
11683 font = tf;
11684 edit_combo(tile,false,cs);
11685 redraw=true;
11686 }
11687
11688 font = tf;
11689 }
11690 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11691 {
11692 FONT *tf = font;
11693 font = tfont;
11694
11695 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11696 {
11697 done=1;
11698 }
11699
11700 font = tf;
11701 }
11702 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11703 {
11704 FONT *tf = font;
11705 font = tfont;
11706
11707 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11708 combopage_animate = combopage_animate ? 0 : 1;
11709 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11710 redraw = true;
11711
11712 font = tf;
11713 }
11714
11715 bdown=true;
11716 }
11717
11718 bool r_click = false;
11719
11720 if(gui_mouse_b()&2 && !bdown)
11721 {
11722 int32_t x=gui_mouse_x()-screen_xofs;
11723 int32_t y=gui_mouse_y()-screen_yofs;
11724
11725 if(y>=0 && y<(208*mul))
11726 {
11727 x=zc_min(zc_max(x,0),(320*mul)-1);
11728 int32_t t;
11729
11730 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11731
11732 bound(t,0,255);
11733 t+=page<<8;
11734
11735 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11736 {
11737 tile=tile2=t;
11738 }
11739 }
11740
11741 bdown = r_click = true;
11742 f=8;
11743 }
11744
11745 REDRAW:
11746
11747 if(gui_mouse_b()==0)
11748 bdown=false;
11749
11750 if((f%8) || InvalidBG == 1)
11751 redraw = true;
11752 if(otl != tile || otl2 != tile2)
11753 {
11754 otl = tile;
11755 otl2 = tile2;
11756 redraw = true;
11757 }
11758
11759 if(redraw || combopage_animate)
11760 draw_combos(page,cs,true);
11761
11762 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11763
11764 if(f&8)
11765 {
11766 int32_t x,y;
11767
11768 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11769 {
11770 if((i>>8)==page)
11771 {
11772 int32_t t=i&255;
11773
11774 x=((t&3) + ((t/52)<<2)) << 5;
11775 y=((t%52)>>2) << 5;
11776
11777 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11778 }
11779 }
11780
11781 SCRFIX();
11782 }
11783
11784 ++f;
11785
11786 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11787 if(r_click)
11788 {
11789 NewMenu rcmenu
11790 {
11791 { "Copy", [&]()
11792 {
11793 go_combos();
11794 copy=zc_min(tile,tile2);
11795 copycnt=abs(tile-tile2)+1;
11796 } },
11797 { "Paste", [&]()
11798 {
11799 if((CHECK_CTRL_CMD) && copy != -1)
11800 {
11801 if(advpaste(tile, tile2, copy))
11802 {
11803 saved=false;
11804 redraw=true;
11805 copy=-1;
11806 }
11807 return;
11808 }
11809
11810 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11811
11812 if(copy>-1)
11813 {
11814 go_combos();
11815 copy_combos(tile,tile2,copy,copycnt,masscopy);
11816 setup_combo_animations();
11817 setup_combo_animations2();
11818 saved=false;
11819 }
11820 } },
11821 { "Adv. Paste", [&]()
11822 {
11823 if(copy > -1)
11824 {
11825 if(advpaste(tile, tile2, copy))
11826 {
11827 saved=false;
11828 redraw=true;
11829 copy=-1;
11830 }
11831 }
11832 } },
11833 { "Swap", [&]()
11834 {
11835 tile=tile2=zc_min(tile,tile2);
11836
11837 if(copy>=0 && tile!=copy)
11838 {
11839 go_combos();
11840
11841 for(int32_t i=0; i<copycnt; i++)
11842 {
11843 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11844 }
11845
11846 saved=false;
11847 setup_combo_animations();
11848 setup_combo_animations2();
11849 }
11850 copy=-1;
11851 } },
11852 { "Delete", [&]()
11853 {
11854 string msg;
11855
11856 if(tile==tile2)
11857 msg = fmt::format("Delete combo {}?",tile);
11858 else
11859 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11860 bool didconfirm = false;
11861 AlertDialog("Confirm Delete",msg,
11862 [&](bool ret,bool)
11863 {
11864 if(ret)
11865 didconfirm = true;
11866 }).show();
11867 if(didconfirm)
11868 {
11869 go_combos();
11870
11871 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11872 clear_combo(i);
11873
11874 tile=tile2=zc_min(tile,tile2);
11875 saved=false;
11876 }
11877 } },
11878 {},
11879 { "Edit", [&]()
11880 {
11881 go_combos();
11882 edit_combo(tile,false,cs);
11883 } },
11884 { "Insert", [&]()
11885 {
11886 int z = tile;
11887 int count = abs(tile-tile2)+1;
11888 tile = zc_min(tile,tile2);
11889 tile2 = MAXCOMBOS;
11890 copy = tile+count;
11891 copycnt = MAXCOMBOS-tile-count;
11892
11893 string msg;
11894
11895 if(count>1)
11896 msg = fmt::format("Insert combos {} - {}?"
11897 " This will offset all of the combos that follow!",tile, copy-1);
11898 else
11899 msg = fmt::format("Insert combo {}?"
11900 " This will offset all of the combos that follow!",tile);
11901
11902 bool didconfirm = false;
11903 AlertDialog("Confirm Insert",msg,
11904 [&](bool ret,bool)
11905 {
11906 if(ret)
11907 didconfirm = true;
11908 }).show();
11909 if(didconfirm)
11910 move_combos(copy, tile2, tile, copycnt);
11911 else return;
11912
11913 copy = -1;
11914 tile2 = tile = z;
11915
11916 //don't allow the user to undo; quest combo references are incorrect -DD
11917 go_combos();
11918 saved = false;
11919 } },
11920 { "Remove", [&]()
11921 {
11922 int z = tile;
11923 int count = abs(tile-tile2)+1;
11924 tile = zc_min(tile,tile2);
11925 tile2 = MAXCOMBOS;
11926 copy = tile+count;
11927 copycnt = MAXCOMBOS-tile-count;
11928
11929 string msg;
11930
11931 if(count>1)
11932 msg = fmt::format("Remove combos {} - {}?"
11933 " This will offset all of the combos that follow!",tile, copy-1);
11934 else
11935 msg = fmt::format("Remove combo {}?"
11936 " This will offset all of the combos that follow!",tile);
11937
11938 bool didconfirm = false;
11939 AlertDialog("Confirm Remove",msg,
11940 [&](bool ret,bool)
11941 {
11942 if(ret)
11943 didconfirm = true;
11944 }).show();
11945 if(didconfirm)
11946 move_combos(tile, tile2, copy, copycnt);
11947 else return;
11948
11949 copy = -1;
11950 tile2 = tile = z;
11951
11952 //don't allow the user to undo; quest combo references are incorrect -DD
11953 go_combos();
11954 saved = false;
11955 } },
11956 {},
11957 { "Locations", [&]()
11958 {
11959 int32_t z = Combo;
11960 Combo = tile;
11961 onComboLocationReport();
11962 Combo = z;
11963 } },
11964 };
11965 rcmenu.pop(window_mouse_x(),window_mouse_y());
11966 redraw = true;
11967 r_click = false;
11968 goto REDRAW;
11969 }
11970
11971 }
11972 while(!done);
11973
11974 while(gui_mouse_b())
11975 rest(1);
11976 comeback();
11977 setup_combo_animations();
11978 setup_combo_animations2();
11979 _selected_combo = tile;
11980 _selected_cset = cs;
11981 popup_zqdialog_end();
11982 return done-1;
11983 }
11984
11985 int32_t onCombos()
11986 {
11987 combo_screen(-1,-1);
11988 refresh(rALL);
11989 return D_O_K;
11990 }
11991
11992 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11993 {
11994 //these are here to bypass compiler warnings about unused arguments
11995 d=d;
11996 c=c;
11997
11998 if(msg==MSG_CLICK)
11999 {
12000 int32_t t=curr_combo.o_tile;
12001 int32_t f=curr_combo.flip;
12002
12003 if(select_tile(t,f,1,CSet,true,0,true))
12004 {
12005 curr_combo.tile=t;
12006 curr_combo.o_tile=t;
12007 curr_combo.flip=f;
12008 return D_REDRAW;
12009 }
12010 }
12011
12012 return D_O_K;
12013 }
12014
12015 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
12016 {
12017 //these are here to bypass compiler warnings about unused arguments
12018 c=c;
12019
12020 if(msg==MSG_DRAW)
12021 {
12022 FONT *f = get_zc_font(font_lfont_l);
12023 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12024 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12025 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12026 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12027 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12028 }
12029
12030 return D_O_K;
12031 }
12032
12033 int32_t click_d_ctile_proc()
12034 {
12035 d_ctile_proc(MSG_CLICK,NULL,0);
12036 return D_REDRAW;
12037 }
12038
12039 int32_t click_d_combo_proc();
12040
12041 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12042 {
12043 if(index<0)
12044 {
12045 *list_size = bidcomboscripts_cnt;
12046 return NULL;
12047 }
12048
12049 return bidcomboscripts[index].first.c_str();
12050 }
12051 12 ListData comboscript_list(comboscriptdroplist, &font);
12052
12053 bool call_combo_editor(int32_t);
12054 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12055 {
12056 FONT* ofont = font;
12057 //CSet = cs;
12058 reset_combo_animations();
12059 reset_combo_animations2();
12060 bool edited = call_combo_editor(c);
12061 font = ofont;
12062
12063 if(freshen)
12064 {
12065 refresh(rALL);
12066 }
12067
12068 setup_combo_animations();
12069 setup_combo_animations2();
12070
12071 return edited;
12072 }
12073
12074 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12075 {
12076 switch(msg)
12077 {
12078 case MSG_CLICK:
12079 {
12080 int32_t cs = d->d2;
12081 int32_t f = 0;
12082
12083 if(select_tile(d->d1,f,1,cs,true))
12084 {
12085 int32_t ok=1;
12086
12087 if(newtilebuf[d->d1].format==tf8Bit)
12088 jwin_alert("Warning",
12089 "You have selected an 8-bit tile.",
12090 "It will not be drawn correctly",
12091 "on the file select screen.",
12092 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12093
12094 return D_REDRAW;
12095 }
12096 }
12097 break;
12098
12099 case MSG_DRAW:
12100 d->w = 32+4;
12101 d->h = 32+4;
12102
12103 BITMAP *buf = create_bitmap_ex(8,16,16);
12104 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12105
12106 if(buf && bigbmp)
12107 {
12108 clear_bitmap(buf);
12109 overtile16(buf,d->d1,0,0,d->fg,0);
12110 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12111 destroy_bitmap(buf);
12112 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12113 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12114 destroy_bitmap(bigbmp);
12115 }
12116
12117 break;
12118 }
12119
12120 return D_O_K;
12121 }
12122
12123 static DIALOG icon_dlg[] =
12124 {
12125 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12126 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12127 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12128 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12129 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12130 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12131 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12132 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12133 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12134 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12135 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12136 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12137 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12138 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12139 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12140 };
12141
12142 int32_t onIcons()
12143 {
12144 PALETTE pal;
12145 // pal = RAMpal;
12146 memcpy(pal,RAMpal,sizeof(RAMpal));
12147 icon_dlg[0].dp2=get_zc_font(font_lfont);
12148
12149 for(int32_t i=0; i<4; i++)
12150 {
12151 icon_dlg[i+2].d1 = QMisc.icons[i];
12152 icon_dlg[i+2].fg = i+6;
12153 load_cset(pal, i+6, pSprite(i+spICON1));
12154 }
12155
12156 zc_set_palette(pal);
12157
12158 large_dialog(icon_dlg);
12159
12160 int32_t ret = do_zqdialog(icon_dlg,7);
12161
12162 if(ret==6)
12163 {
12164 for(int32_t i=0; i<4; i++)
12165 {
12166 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12167 {
12168 QMisc.icons[i] = icon_dlg[i+2].d1;
12169 saved=false;
12170 }
12171 }
12172 }
12173
12174 zc_set_palette(RAMpal);
12175 return D_O_K;
12176 }
12177
12178 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12179 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12180 {
12181 if(msg == MSG_DRAW)
12182 {
12183 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12184 }
12185
12186 return D_O_K;
12187 }
12188
12189 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12190 {
12191 switch(msg)
12192 {
12193 case MSG_CLICK:
12194 {
12195 if((d->flags&D_NOCLICK))
12196 break;
12197
12198 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12199 int32_t combo2;
12200 int32_t cs;
12201
12202 if(CHECK_ALT) //place selected cmb/cs
12203 {
12204 if(gui_mouse_b()&1)
12205 {
12206 if(!CHECK_SHIFT)
12207 d->d1 = Combo;
12208 d->fg = CSet;
12209 }
12210
12211 return ret|D_REDRAW;
12212 }
12213 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12214 {
12215 d->d1=0;
12216 d->fg=0;
12217 return ret|D_REDRAW;
12218 }
12219 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12220 {
12221 combo2=d->d1;
12222 cs=d->fg;
12223
12224 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12225 {
12226 d->d1=combo2;
12227 d->fg=cs;
12228 }
12229
12230 return ret|D_REDRAW;
12231 }
12232 else return ret|D_REDRAWME;
12233 }
12234 break;
12235
12236 case MSG_DRAW:
12237 {
12238 d->w = 32;
12239 d->h = 32;
12240
12241 BITMAP *buf = create_bitmap_ex(8,16,16);
12242 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12243
12244 if(buf && bigbmp)
12245 {
12246 clear_bitmap(buf);
12247
12248 if(d->d1==-1) // Display curr_combo instead of combobuf
12249 {
12250 newcombo hold = combobuf[0];
12251 combobuf[0] = curr_combo;
12252 putcombo(buf,0,0,0,d->fg);
12253 combobuf[0] = hold;
12254 }
12255 else if(d->d1)
12256 {
12257 putcombo(buf,0,0,d->d1,d->fg);
12258 }
12259
12260 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12261 destroy_bitmap(buf);
12262 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12263 destroy_bitmap(bigbmp);
12264 }
12265 }
12266 break;
12267 }
12268 return D_O_K;
12269 }
12270
12271 // Hey, let's have a few hundred more lines of code, why not.
12272
12273 #define MR_4BIT 0
12274 #define MR_8BIT 1
12275
12276 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12277 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12278 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12279
12280 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12281 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12282
12283 static int32_t massRecolorDraggedColor=-1;
12284 static int32_t massRecolorCSet;
12285 static bool massRecolorIgnoreBlank=true;
12286 static byte massRecolorType=MR_4BIT;
12287
12288 // Shows the sets of colors to replace from/to.
12289 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12290 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12291 #define D_CSET D_USER
12292 #define D_SETTABLE (D_USER<<1)
12293 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12294 {
12295 BITMAP* bmp=screen;
12296 int32_t colorWidth=(d->w-4)/16;
12297 byte* colors=static_cast<byte*>(d->dp);
12298
12299 switch(msg)
12300 {
12301 case MSG_DRAW:
12302 {
12303 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12304
12305 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12306 for(int32_t c=0; c<16; c++)
12307 {
12308 rectfill(bmp,
12309 d->x+2+c*colorWidth, d->y+2,
12310 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12311 baseColor+colors[c]);
12312 }
12313 }
12314 break;
12315
12316 case MSG_LPRESS:
12317 {
12318 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12319
12320 if(x >= 0 && x < 16) //sanity check!
12321 {
12322 massRecolorDraggedColor=colors[x];
12323 }
12324 }
12325 break;
12326
12327 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12328 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12329 {
12330 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12331 if(x >= 0 && x < 16) //sanity check!
12332 {
12333 colors[x]=massRecolorDraggedColor;
12334 d->flags|=D_DIRTY;
12335 }
12336 }
12337 massRecolorDraggedColor=-1;
12338 break;
12339 }
12340
12341 return D_O_K;
12342 }
12343
12344 // Used for the full palette in 8-bit mode.
12345 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12346 {
12347 BITMAP* bmp=screen;
12348 int colorWidth=(d->w-4)/16;
12349 d->h = 4+(colorWidth*14);
12350 int colorHeight=colorWidth;
12351
12352 switch(msg)
12353 {
12354 case MSG_DRAW:
12355 {
12356 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12357 for(int cset=0; cset<=13; cset++)
12358 {
12359 for(int color=0; color<16; color++)
12360 {
12361 rectfill(bmp,
12362 d->x+2+color*colorWidth,
12363 d->y+2+cset*colorHeight,
12364 d->x+2+((color+1)*colorWidth)-1,
12365 d->y+2+((cset+1)*colorHeight)-1,
12366 cset*16+color);
12367 }
12368 }
12369 }
12370 break;
12371
12372 case MSG_LPRESS:
12373 {
12374 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12375 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12376 massRecolorDraggedColor=cset*16+color;
12377 }
12378 break;
12379 }
12380
12381 return D_O_K;
12382 }
12383
12384 static DIALOG recolor_4bit_dlg[] =
12385 {
12386 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12387 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12388
12389 // 1
12390 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12391 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12392 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12393 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12394
12395 // 5
12396 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12397 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12398 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12399 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12400 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12401 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12402 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12403 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12404 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12405 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12406 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12407 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12408 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12409 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12410 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12411
12412 // 20
12413 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12414 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12415 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12416 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12417 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12418
12419 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12420 };
12421
12422 #define MR4_SRC_COLORS 2
12423 #define MR4_DEST_COLORS 4
12424 #define MR4_8BIT_EFFECT_START 6
12425 #define MR4_IGNORE_BLANK 20
12426 #define MR4_RESET 21
12427 #define MR4_SWITCH 22
12428 #define MR4_OK 23
12429 #define MR4_CANCEL 24
12430
12431 static DIALOG recolor_8bit_dlg[] =
12432 {
12433 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12434 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12435
12436 // 1
12437 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12438 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12439 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12440 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12441 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12442
12443 // 6
12444 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12445 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12446 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12447 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12448 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12449
12450 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12451 };
12452
12453 #define MR8_SRC_COLORS 2
12454 #define MR8_DEST_COLORS 4
12455 #define MR8_PALETTE 5
12456 #define MR8_IGNORE_BLANK 6
12457 #define MR8_RESET 7
12458 #define MR8_SWITCH 8
12459 #define MR8_OK 9
12460 #define MR8_CANCEL 10
12461
12462 static void massRecolorInit(int32_t cset)
12463 {
12464 massRecolorDraggedColor=-1;
12465 massRecolorCSet=cset;
12466
12467 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12468 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12469
12470 for(int32_t i=0; i<=13; i++)
12471 {
12472 if((massRecolor8BitCSets&(1<<i))!=0)
12473 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12474 else
12475 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12476 }
12477
12478 if(massRecolorIgnoreBlank)
12479 {
12480 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12481 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12482 }
12483 else
12484 {
12485 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12486 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12487 }
12488
12489 large_dialog(recolor_4bit_dlg);
12490 large_dialog(recolor_8bit_dlg);
12491
12492 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12493 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12494 {
12495 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12496 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12497 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12498 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12499
12500 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12501 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12502 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12503 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12504 recolor_8bit_dlg[MR8_PALETTE].x++;
12505 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12506 recolor_8bit_dlg[MR8_PALETTE].y++;
12507 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12508 }
12509 }
12510
12511 static void massRecolorApplyChanges()
12512 {
12513 massRecolor8BitCSets=0;
12514 for(int32_t i=0; i<=13; i++)
12515 {
12516 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12517 massRecolor8BitCSets|=1<<i;
12518 }
12519
12520 if(massRecolorType==MR_4BIT)
12521 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12522 else
12523 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12524 }
12525
12526 static bool massRecolorSetup(int32_t cset)
12527 {
12528 massRecolorInit(cset);
12529
12530 // Remember the current colors in case the user cancels.
12531 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12532 for(int32_t i=0; i<16; i++)
12533 {
12534 oldDest4Bit[i]=massRecolorDest4Bit[i];
12535 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12536 oldDest8Bit[i]=massRecolorDest8Bit[i];
12537 }
12538
12539 byte type=massRecolorType;
12540 int32_t ret;
12541 do
12542 {
12543 HANDLE_CLOSE_ZQDLG();
12544 if(exiting_program) break;
12545 if(type==MR_4BIT)
12546 {
12547 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12548 if(ret==MR4_SWITCH)
12549 type=MR_8BIT;
12550 }
12551 else
12552 {
12553 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12554 if(ret==MR8_SWITCH)
12555 type=MR_4BIT;
12556 }
12557 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12558
12559 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12560 {
12561 for(int32_t i=0; i<16; i++)
12562 {
12563 massRecolorDest4Bit[i]=oldDest4Bit[i];
12564 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12565 massRecolorDest8Bit[i]=oldDest8Bit[i];
12566 }
12567 return false;
12568 }
12569
12570 // OK
12571 massRecolorType=type;
12572 massRecolorApplyChanges();
12573 return true;
12574 }
12575
12576 static void massRecolorApply4Bit(int32_t tile)
12577 {
12578 byte buf[256];
12579 unpack_tile(newtilebuf, tile, 0, true);
12580
12581 if(newtilebuf[tile].format==tf4Bit)
12582 {
12583 for(int32_t i=0; i<256; i++)
12584 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12585 }
12586 else // 8-bit
12587 {
12588 for(int32_t i=0; i<256; i++)
12589 {
12590 word cset=unpackbuf[i]>>4;
12591 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12592 {
12593 word color=unpackbuf[i]&15;
12594 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12595 }
12596 else
12597 buf[i]=unpackbuf[i];
12598 }
12599 }
12600
12601 pack_tile(newtilebuf, buf, tile);
12602 }
12603
12604 static void massRecolorApply8Bit(int32_t tile)
12605 {
12606 byte buf[256];
12607 unpack_tile(newtilebuf, tile, 0, true);
12608
12609 for(int32_t i=0; i<256; i++)
12610 {
12611 byte color=unpackbuf[i];
12612 for(int32_t j=0; j<16; j++)
12613 {
12614 if(massRecolorSrc8Bit[j]==color)
12615 {
12616 color=massRecolorDest8Bit[j];
12617 break;
12618 }
12619 }
12620 buf[i]=color;
12621 }
12622
12623 pack_tile(newtilebuf, buf, tile);
12624 }
12625
12626 static void massRecolorApply(int32_t tile)
12627 {
12628 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12629 return;
12630
12631 if(massRecolorType==MR_4BIT)
12632 massRecolorApply4Bit(tile);
12633 else // 8-bit
12634 {
12635 if(newtilebuf[tile].format==tf4Bit)
12636 return;
12637 massRecolorApply8Bit(tile);
12638 }
12639 }
12640
12641 static void massRecolorReset4Bit()
12642 {
12643 for(int32_t i=0; i<16; i++)
12644 massRecolorDest4Bit[i]=i;
12645 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12646 }
12647
12648 static void massRecolorReset8Bit()
12649 {
12650 for(int32_t i=0; i<16; i++)
12651 {
12652 massRecolorSrc8Bit[i]=0;
12653 massRecolorDest8Bit[i]=0;
12654 }
12655
12656 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12657 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12658 }
12659
12660 8 void center_zq_tiles_dialogs()
12661 {
12662 8 jwin_center_dialog(create_relational_tiles_dlg);
12663 8 jwin_center_dialog(icon_dlg);
12664 8 jwin_center_dialog(leech_dlg);
12665 8 jwin_center_dialog(move_textbox_list_dlg);
12666 8 jwin_center_dialog(recolor_4bit_dlg);
12667 8 jwin_center_dialog(recolor_8bit_dlg);
12668 8 }
12669
12670 //.ZCOMBO
12671
12672 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12673 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12674
12675 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12676 dword section_version, int32_t index, int32_t count)
12677 {
12678 newcombo temp_combo;
12679 for ( int32_t tilect = 0; tilect < count; tilect++ )
12680 {
12681 temp_combo.clear();
12682 if(!p_igetw(&temp_combo.tile,f))
12683 {
12684 return 0;
12685 }
12686 temp_combo.o_tile = temp_combo.tile;
12687
12688 if(!p_getc(&temp_combo.flip,f))
12689 {
12690 return 0;
12691 }
12692
12693 if(!p_getc(&temp_combo.walk,f))
12694 {
12695 return 0;
12696 }
12697
12698 if(!p_getc(&temp_combo.type,f))
12699 {
12700 return 0;
12701 }
12702
12703 if(!p_getc(&temp_combo.csets,f))
12704 {
12705 return 0;
12706 }
12707
12708 if(!p_getc(&temp_combo.frames,f))
12709 {
12710 return 0;
12711 }
12712
12713 if(!p_getc(&temp_combo.speed,f))
12714 {
12715 return 0;
12716 }
12717
12718 if(!p_igetw(&temp_combo.nextcombo,f))
12719 {
12720 return 0;
12721 }
12722
12723 if(!p_getc(&temp_combo.nextcset,f))
12724 {
12725 return 0;
12726 }
12727
12728 if(!p_getc(&temp_combo.flag,f))
12729 {
12730 return 0;
12731 }
12732
12733 if(!p_getc(&temp_combo.skipanim,f))
12734 {
12735 return 0;
12736 }
12737
12738 if(!p_igetw(&temp_combo.nexttimer,f))
12739 {
12740 return 0;
12741 }
12742
12743 if(!p_getc(&temp_combo.skipanimy,f))
12744 {
12745 return 0;
12746 }
12747
12748 if(!p_getc(&temp_combo.animflags,f))
12749 {
12750 return 0;
12751 }
12752
12753 //2.55 starts here
12754 if ( zversion >= 0x255 )
12755 {
12756 if ( section_version >= 12 )
12757 {
12758 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12759 {
12760 if(!p_igetl(&temp_combo.attributes[q],f))
12761 {
12762 return 0;
12763 }
12764 }
12765 if(!p_igetl(&temp_combo.usrflags,f))
12766 {
12767 return 0;
12768 }
12769 for ( int32_t q = 0; q < 3; q++ )
12770 {
12771 if(!p_igetl(&temp_combo.triggerflags[q],f))
12772 {
12773 return 0;
12774 }
12775 }
12776
12777 if(!p_igetl(&temp_combo.triggerlevel,f))
12778 {
12779 return 0;
12780 }
12781 if(section_version >= 22)
12782 {
12783 if(!p_getc(&temp_combo.triggerbtn,f))
12784 {
12785 return 0;
12786 }
12787 }
12788 if(section_version < 23)
12789 {
12790 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12791 {
12792 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12793 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12794 case cTRIGGERGENERIC: case cCSWITCH:
12795 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12796 }
12797 }
12798 if(section_version >= 24)
12799 {
12800 if(!p_getc(&temp_combo.triggeritem,f))
12801 {
12802 return 0;
12803 }
12804 if(!p_getc(&temp_combo.trigtimer,f))
12805 {
12806 return 0;
12807 }
12808 }
12809 if(section_version >= 25)
12810 {
12811 if(!p_getc(&temp_combo.trigsfx,f))
12812 {
12813 return 0;
12814 }
12815 }
12816 else
12817 {
12818 switch(temp_combo.type)
12819 {
12820 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12821 if(!(temp_combo.usrflags & cflag3))
12822 temp_combo.attribytes[3] = WAV_DOOR;
12823 temp_combo.usrflags &= ~cflag3;
12824 break;
12825 }
12826 }
12827 if(section_version < 26)
12828 {
12829 if(temp_combo.type == cARMOS)
12830 {
12831 if(temp_combo.usrflags & cflag1)
12832 temp_combo.usrflags |= cflag3;
12833 }
12834 }
12835 if(section_version >= 27)
12836 {
12837 if(!p_igetl(&temp_combo.trigchange,f))
12838 {
12839 return qe_invalid;
12840 }
12841 }
12842 else
12843 {
12844 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12845 temp_combo.trigchange = 1;
12846 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12847 temp_combo.trigchange = -1;
12848 else temp_combo.trigchange = 0;
12849 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12850 }
12851 if(section_version >= 29)
12852 {
12853 if(!p_igetw(&temp_combo.trigprox,f))
12854 {
12855 return qe_invalid;
12856 }
12857 if(!p_getc(&temp_combo.trigctr,f))
12858 {
12859 return qe_invalid;
12860 }
12861 if(!p_igetl(&temp_combo.trigctramnt,f))
12862 {
12863 return qe_invalid;
12864 }
12865 }
12866 else
12867 {
12868 temp_combo.trigprox = 0;
12869 temp_combo.trigctr = 0;
12870 temp_combo.trigctramnt = 0;
12871 }
12872 if(section_version >= 30)
12873 {
12874 if(!p_getc(&temp_combo.triglbeam,f))
12875 {
12876 return qe_invalid;
12877 }
12878 }
12879 else temp_combo.triglbeam = 0;
12880 if(section_version >= 31)
12881 {
12882 if(!p_getc(&temp_combo.trigcschange,f))
12883 {
12884 return qe_invalid;
12885 }
12886 if(!p_igetw(&temp_combo.spawnitem,f))
12887 {
12888 return qe_invalid;
12889 }
12890 if(!p_igetw(&temp_combo.spawnenemy,f))
12891 {
12892 return qe_invalid;
12893 }
12894 if(!p_getc(&temp_combo.exstate,f))
12895 {
12896 return qe_invalid;
12897 }
12898 if(!p_igetl(&temp_combo.spawnip,f))
12899 {
12900 return qe_invalid;
12901 }
12902 if(!p_getc(&temp_combo.trigcopycat,f))
12903 {
12904 return qe_invalid;
12905 }
12906 }
12907 else
12908 {
12909 temp_combo.trigcschange = 0;
12910 temp_combo.spawnitem = 0;
12911 temp_combo.spawnenemy = 0;
12912 temp_combo.exstate = -1;
12913 temp_combo.spawnip = 0;
12914 temp_combo.trigcopycat = 0;
12915 }
12916 if(section_version >= 32)
12917 {
12918 if(!p_getc(&temp_combo.trigcooldown,f))
12919 {
12920 return qe_invalid;
12921 }
12922 }
12923 else
12924 {
12925 temp_combo.trigcooldown = 0;
12926 }
12927 char label[12];
12928 label[11] = '\0';
12929 for ( int32_t q = 0; q < 11; q++ )
12930 {
12931 if(!p_getc(&label[q],f))
12932 {
12933 return 0;
12934 }
12935 }
12936 temp_combo.label = label;
12937 }
12938 if ( section_version >= 13 )
12939 {
12940 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12941 {
12942 if(!p_getc(&temp_combo.attribytes[q],f))
12943 {
12944 return 0;
12945 }
12946 }
12947
12948 }
12949 }
12950
12951 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12952 {
12953 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12954 {
12955 combobuf[index+(tilect)] = temp_combo;
12956 }
12957 }
12958 }
12959
12960 return 1;
12961 }
12962
12963 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12964 {
12965 dword section_version=0;
12966 int32_t zversion = 0;
12967 int32_t zbuild = 0;
12968
12969 if(!p_igetl(&zversion,f))
12970 {
12971 return 0;
12972 }
12973 if(!p_igetl(&zbuild,f))
12974 {
12975 return 0;
12976 }
12977 if(!p_igetw(&section_version,f))
12978 {
12979 return 0;
12980 }
12981 if(!read_deprecated_section_cversion(f))
12982 {
12983 return 0;
12984 }
12985
12986 if ( zversion > ZELDA_VERSION )
12987 {
12988 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12989 return 0;
12990 }
12991
12992 else if ( ( section_version > V_COMBOS ))
12993 {
12994 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d)\n", section_version);
12995 return 0;
12996
12997 }
12998 else
12999 {
13000 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13001 }
13002
13003 int32_t index = 0;
13004 int32_t count = 0;
13005
13006 //tile id
13007 if(!p_igetl(&index,f))
13008 {
13009 return 0;
13010 }
13011 if(start > -1) index = start;
13012
13013 //tile count
13014 if(!p_igetl(&count,f))
13015 {
13016 return 0;
13017 }
13018 reset_combo_animations();
13019 reset_combo_animations2();
13020
13021 if(section_version < 33)
13022 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,index,count);
13023
13024 newcombo temp_combo;
13025 size_t end = index+count;
13026 for ( size_t q = index; q < end; q++ )
13027 {
13028 auto ret = readcombo_loop(f,section_version,temp_combo);
13029 if(ret) return 0;
13030
13031 if ( !(skip && q-1 < skip) )
13032 {
13033 if ( !nooverwrite || combobuf[q].is_blank() )
13034 {
13035 combobuf[q] = temp_combo;
13036 }
13037 }
13038 }
13039
13040 return 1;
13041 }
13042 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13043 {
13044 return readcombofile(f,skip,nooverwrite,start);
13045 }
13046 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13047 {
13048 dword section_version=V_COMBOS;
13049 int32_t zversion = ZELDA_VERSION;
13050 int32_t zbuild = VERSION_BUILD;
13051
13052 if(!p_iputl(zversion,f))
13053 {
13054 return 0;
13055 }
13056 if(!p_iputl(zbuild,f))
13057 {
13058 return 0;
13059 }
13060 if(!p_iputw(section_version,f))
13061 {
13062 return 0;
13063 }
13064
13065 if(!write_deprecated_section_cversion(section_version,f))
13066 {
13067 return 0;
13068 }
13069
13070 //start tile id
13071 if(!p_iputl(index,f))
13072 {
13073 return 0;
13074 }
13075
13076 //count
13077 if(!p_iputl(count,f))
13078 {
13079 return 0;
13080 }
13081 reset_combo_animations();
13082 reset_combo_animations2();
13083 size_t end = index+count;
13084 for(size_t q = index; q < end; ++q)
13085 {
13086 if(writecombo_loop(f, section_version, combobuf[q]))
13087 return 0;
13088 }
13089
13090 return 1;
13091
13092 }
13093
13094 //.ZALIAS
13095
13096
13097 //.ZALIAS
13098
13099 int32_t readcomboaliasfile(PACKFILE *f)
13100 {
13101 dword section_version=0;
13102 int32_t zversion = 0;
13103 int32_t zbuild = 0;
13104 word tempword = 0;
13105
13106 if(!p_igetl(&zversion,f))
13107 {
13108 return 0;
13109 }
13110 if(!p_igetl(&zbuild,f))
13111 {
13112 return 0;
13113 }
13114 if(!p_igetw(&section_version,f))
13115 {
13116 return 0;
13117 }
13118 if(!read_deprecated_section_cversion(f))
13119 {
13120 return 0;
13121 }
13122 al_trace("readoneweapon section_version: %d\n", section_version);
13123
13124 if ( zversion > ZELDA_VERSION )
13125 {
13126 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13127 return 0;
13128 }
13129
13130 else if ( ( section_version > V_COMBOALIASES ))
13131 {
13132 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13133 return 0;
13134
13135 }
13136 else
13137 {
13138 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13139 }
13140
13141 int32_t index = 0;
13142 int32_t count = 0;
13143 int32_t count2 = 0;
13144 byte tempcset = 0;
13145
13146 //tile id
13147 if(!p_igetl(&index,f))
13148 {
13149 return 0;
13150 }
13151 al_trace("Reading combo: index(%d)\n", index);
13152
13153 //tile count
13154 if(!p_igetl(&count,f))
13155 {
13156 return 0;
13157 }
13158 al_trace("Reading combo: count(%d)\n", count);
13159
13160 combo_alias temp_alias;
13161
13162 for ( int32_t tilect = 0; tilect < count; tilect++ )
13163 {
13164 temp_alias.clear();
13165 if(!p_igetw(&temp_alias.combo,f))
13166 {
13167 return 0;
13168 }
13169
13170 if(!p_getc(&temp_alias.cset,f))
13171 {
13172 return 0;
13173 }
13174
13175
13176
13177 if(!p_igetl(&count2,f))
13178 {
13179 return 0;
13180 }
13181 al_trace("Read, Combo alias count is: %d\n", count2);
13182 if(!p_getc(&temp_alias.width,f))
13183 {
13184 return 0;
13185 }
13186
13187 if(!p_getc(&temp_alias.height,f))
13188 {
13189 return 0;
13190 }
13191
13192 if(!p_getc(&temp_alias.layermask,f))
13193 {
13194 return 0;
13195 }
13196 //These values are flexible, and may differ in size, so we delete them
13197 //and recreate them at the correct size on the pointer.
13198 temp_alias.combos.clear();
13199 temp_alias.csets.clear();
13200 for(int32_t k=0; k<count2; k++)
13201 {
13202 if(!p_igetw(&tempword,f))
13203 {
13204 return 0;
13205 }
13206 else
13207 {
13208
13209
13210 temp_alias.combos[k] = tempword;
13211 }
13212 }
13213
13214 for(int32_t k=0; k<count2; k++)
13215 {
13216 if(!p_getc(&tempcset,f))
13217 //if(!p_getc(&temp_alias.csets[k],f))
13218 {
13219 return 0;
13220 }
13221 else
13222 {
13223
13224 temp_alias.csets[k] = tempcset;
13225 }
13226 }
13227 combo_aliases[index+(tilect)] = temp_alias;
13228 }
13229
13230 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13231
13232
13233 return 1;
13234
13235 }
13236
13237 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13238 {
13239 dword section_version=0;
13240 int32_t zversion = 0;
13241 int32_t zbuild = 0;
13242
13243 if(!p_igetl(&zversion,f))
13244 {
13245 return 0;
13246 }
13247 if(!p_igetl(&zbuild,f))
13248 {
13249 return 0;
13250 }
13251 if(!p_igetw(&section_version,f))
13252 {
13253 return 0;
13254 }
13255 if(!read_deprecated_section_cversion(f))
13256 {
13257 return 0;
13258 }
13259 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13260
13261 if ( zversion > ZELDA_VERSION )
13262 {
13263 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13264 return 0;
13265 }
13266 else if ( ( section_version > V_COMBOALIASES ))
13267 {
13268 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13269 return 0;
13270
13271 }
13272 else
13273 {
13274 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13275 }
13276
13277 int32_t index = 0;
13278 int32_t count = 0;
13279 int32_t count2 = 0;
13280 byte tempcset = 0;
13281 word tempword = 0;
13282
13283
13284 //tile id
13285 if(!p_igetl(&index,f))
13286 {
13287 return 0;
13288 }
13289 al_trace("Reading tile: index(%d)\n", index);
13290
13291 //tile count
13292 if(!p_igetl(&count,f))
13293 {
13294 return 0;
13295 }
13296 al_trace("Reading tile: count(%d)\n", count);
13297
13298
13299 combo_alias temp_alias;
13300
13301 for ( int32_t tilect = 0; tilect < count; tilect++ )
13302 {
13303 temp_alias.clear();
13304 if(!p_igetw(&temp_alias.combo,f))
13305 {
13306 return 0;
13307 }
13308
13309 if(!p_getc(&temp_alias.cset,f))
13310 {
13311 return 0;
13312 }
13313
13314 int32_t count2 = 0;
13315
13316 if(!p_igetl(&count2,f))
13317 {
13318 return 0;
13319 }
13320
13321 if(!p_getc(&temp_alias.width,f))
13322 {
13323 return 0;
13324 }
13325
13326 if(!p_getc(&temp_alias.height,f))
13327 {
13328 return 0;
13329 }
13330
13331 if(!p_getc(&temp_alias.layermask,f))
13332 {
13333 return 0;
13334 }
13335 //These values are flexible, and may differ in size, so we delete them
13336 //and recreate them at the correct size on the pointer.
13337 temp_alias.combos.clear();
13338 temp_alias.csets.clear();
13339
13340 for(int32_t k=0; k<count2; k++)
13341 {
13342 if(!p_igetw(&tempword,f))
13343 {
13344 return 0;
13345 }
13346 else
13347 {
13348 temp_alias.combos[k] = tempword;
13349 }
13350 }
13351
13352 for(int32_t k=0; k<count2; k++)
13353 {
13354 if(!p_getc(&tempcset,f))
13355 {
13356 return 0;
13357 }
13358 else
13359 {
13360 temp_alias.csets[k] = tempcset;
13361 }
13362 }
13363
13364 if ( start+(tilect) < MAXCOMBOALIASES )
13365 {
13366 combo_aliases[start + (tilect)] = temp_alias;
13367 }
13368 }
13369 return 1;
13370 }
13371 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13372 {
13373 al_trace("Running writecomboaliasfile\n");
13374 dword section_version=V_COMBOALIASES;
13375 int32_t zversion = ZELDA_VERSION;
13376 int32_t zbuild = VERSION_BUILD;
13377
13378 if(!p_iputl(zversion,f))
13379 {
13380 return 0;
13381 }
13382 if(!p_iputl(zbuild,f))
13383 {
13384 return 0;
13385 }
13386 if(!p_iputw(section_version,f))
13387 {
13388 return 0;
13389 }
13390
13391 if(!write_deprecated_section_cversion(section_version,f))
13392 {
13393 return 0;
13394 }
13395
13396 //start tile id
13397 if(!p_iputl(index,f))
13398 {
13399 return 0;
13400 }
13401
13402 //count
13403 if(!p_iputl(count,f))
13404 {
13405 return 0;
13406 }
13407
13408 for ( int32_t tilect = 0; tilect < count; tilect++ )
13409 {
13410
13411 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13412 {
13413 return 0;
13414 }
13415
13416 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13417 {
13418 return 0;
13419 }
13420
13421 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13422
13423 if(!p_iputl(count2,f))
13424 {
13425 return 0;
13426 }
13427 al_trace("Write`, Combo alias count is: %d\n", count2);
13428
13429 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13430 {
13431 return 0;
13432 }
13433
13434 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13435 {
13436 return 0;
13437 }
13438
13439 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13440 {
13441 return 0;
13442 }
13443
13444 for(int32_t k=0; k<count2; k++)
13445 {
13446 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13447 {
13448 return 0;
13449 }
13450 }
13451
13452 for(int32_t k=0; k<count2; k++)
13453 {
13454 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13455 {
13456 return 0;
13457 }
13458 }
13459 }
13460
13461 return 1;
13462
13463 }
13464